C++网络编程学习:对socket select网络模型的优化
- 使用的语言为C/C++
- 源码支持的平台为:Windows / Linux
- 东西不多,简单记录一下,今后可能会补充
零、思路与流程
select网络模型的大概流程如下:
1.获取一个至三个fd_set
集合,获取一个timeval
2.select
函数对fd_set
集合进行选择筛选
3.FD_ISSET
函数依据fd_set
集合遍历查找待处理事件
1 | WINSOCK_API_LINKAGE int WSAAPI select( |
一、对fd_set
的优化
首先,我们可以对fd_set
的相关操作进行优化。
之前,我们每进行一次select
操作,都要使用循环把所有的已连接socket放到fd_set
集合中,随后进行选择操作。但是当连接数很大、select操作频繁时,不断的新建fd_set
并用循环放入socket,很明显会大大增大系统的消耗。
由于fd_set
集合中一定存放的是当前所有的socket,由此,我们可以建立两个fd_set
集合与一个bool
变量。bool
变量用来表示socket的组成是否发生了变化,当有客户端加入或断开时,该变量为true,否则为false。
我们使用一个fd_set
集合储存”老的”socket集合,当socket集合没有发生变化时,我们另一个新fd_set
集合直接使用memcpy
函数复制老集合中的内容,从而避免从头循环放入。当socket集合发生变化时,新集合直接循环从头录入,随后老集合使用memcpy
函数把新集合内的内容复制过去,方便下一次使用。
这样,我们即可大大减少关于fd_set
集合初始化的消耗。
二、对select
函数的优化
当前我的代码只对read可读集合进行操作,并没有write可写集合与except异常集合的操作,所以我的select目前第三、第四个参数都传了空。这样可以增加一点select的效率。
1 | select(_sock+1,&fdRead,0,0,&s_t); |
其余因为select函数被封装了,目前就我的水平来言应该没法做进一步的优化,可能以后会有吧。
三、对FD_ISSET
的优化
这是select架构里吃资源的大头,当socket连接数很大时,显而易见的是这种O(N^2)的查询方法会极大的消耗资源。对此我们可以引入map加快查找操作。
1 | std::map<socket,Client> _clients; |
socket当键,客户端对象当值。根据select处理后的fd_set
集合内的socket进行查找。效率提高为O(lgN)。