C++网络编程学习:对socket select网络模型的优化

网络编程学习记录

  • 使用的语言为C/C++
  • 源码支持的平台为:Windows / Linux

笔记一:建立基础TCP服务端/客户端  点我跳转
笔记二:网络数据报文的收发  点我跳转
笔记三:升级为select网络模型  点我跳转
笔记四:跨平台支持Windows、Linux系统  点我跳转
笔记五:源码的封装  点我跳转
笔记六:缓冲区溢出与粘包分包  点我跳转
笔记七:服务端多线程分离业务处理高负载  点我跳转
笔记八:对socket select网络模型的优化  点我跳转
笔记九:消息接收与发送分离  点我跳转


  • 东西不多,简单记录一下,今后可能会补充

零、思路与流程

select网络模型的大概流程如下:

1.获取一个至三个fd_set集合,获取一个timeval
2.select函数对fd_set集合进行选择筛选
3.FD_ISSET函数依据fd_set集合遍历查找待处理事件

select相关详细内容点我

WINSOCK_API_LINKAGE int WSAAPI select(
		int nfds,//是指待监听集合里的范围 即待监听数量最大值+1
		fd_set *readfds,//待监听的可读文件集合 
		fd_set *writefds,//待监听的可写文件集合  
		fd_set *exceptfds,//待监听的异常文件集合  
		const PTIMEVAL timeout);//超时设置 传入NULL为阻塞模式 传入timeval结构体为非阻塞模式

	返回值为满足条件的待监听socket数量和,如果出错返回-1,如果超时返回0

一、对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的效率。

select(_sock+1,&fdRead,0,0,&s_t); 

  其余因为select函数被封装了,目前就我的水平来言应该没法做进一步的优化,可能以后会有吧。

三、对FD_ISSET的优化

  这是select架构里吃资源的大头,当socket连接数很大时,显而易见的是这种O(N^2)的查询方法会极大的消耗资源。对此我们可以引入map加快查找操作。

std::map<socket,Client> _clients;

  socket当键,客户端对象当值。根据select处理后的fd_set集合内的socket进行查找。效率提高为O(lgN)。

扫描二维码关注公众号,回复: 12891776 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_45698148/article/details/113895569