基本上所有的客户端都是可写的,所有的客户端都加入到可写检测列表中,select每次都会检测到可写。
在客户端和服务器交互的低频场景下,可读检测列表可能并不会每秒都接受到信号,但是可写检测列表一直都会返回信号,所以可以设置是否需要写函数,过滤不需要写的套接字。(select深度剖析后再看)
CELLServer.hpp的修改
bool DoSelect()
{
//计算可读集合
if (_clients_change)
{
_clients_change = false;
//清理集合
_fdRead.zero();
//将描述符(socket)加入集合
_maxSock = _clients.begin()->second->sockfd();
for (auto iter : _clients)
{
_fdRead.add(iter.second->sockfd());
if (_maxSock < iter.second->sockfd())
{
_maxSock = iter.second->sockfd();
}
}
_fdRead_bak.copy(_fdRead);
}
else {
_fdRead.copy(_fdRead_bak);
}
//计算可写集合
bool bNeedWrite = false;
_fdWrite.zero();
for (auto iter : _clients)
{ //需要写数据的客户端,才加入fd_set检测是否可写
if (iter.second->needWrite())
{
bNeedWrite = true;
_fdWrite.add(iter.second->sockfd());
}
}
///nfds 是一个整数值 是指fd_set集合中所有描述符(socket)的范围,而不是数量
///既是所有文件描述符最大值+1 在Windows中这个参数可以写0
timeval t{ 0,1 };
int ret = 0;
if (bNeedWrite)
{
ret = select(_maxSock + 1, _fdRead.fdset(), _fdWrite.fdset(), nullptr, &t);
}
else {
ret = select(_maxSock + 1, _fdRead.fdset(), nullptr, nullptr, &t);
}
if (ret < 0)
{
CELLLog_Error("CELLServer%d.OnRun.select Error exit:errno<%d>,errmsg<%s>", _id,errno,strerror(errno));
return false;
}
else if (ret == 0)
{
return true;
}
ReadData();
WriteData();
return true;
}
这样极大的减少了select的消耗