//备份客户socket fd_set
fd_set _fdRead_bak;
//客户列表是否有变化
bool _clients_change;
SOCKET _maxSock;
std::map<SOCKET,ClientSocket*>_clients;
//Deal msg
bool OnRun()
{
_clients_change = true;
while (isRun())
{
//2.没有新的client加入,clientbuff就是0
if (_clientsBuff.size() > 0)
{
//将共享缓冲区的所有pclient返回给正式队列
std::lock_guard<std::mutex>lock(_mutex);
//从clientsBuff 0 开始,将_clientsBuff vector内所有元素,用pClient接收
//也就是在C++11中,只有vector这样的容器才能使用
for (auto pClient : _clientsBuff)
{
_clients[pClient->sockfd()] = pClient;
}
//将_clientBuff中的所有元素传输到正式队列_client中后清空_clientsBuff
_clientsBuff.clear();
_clients_change = true;
}
//3.但是clients队列有现有的client,不为空
//如果一个消息都没有直接return
if (_clients.empty())
{
//看看能不能删
std::chrono::milliseconds sleeptime1(1);
std::this_thread::sleep_for(sleeptime1);
continue;
}
//CellServer里只添加从EasyTcpServer(生产者)中添加的client
fd_set fdRead;
FD_ZERO(&fdRead);
//4.clients_change 为false直接复制,复制后的其实不止之前接收的数量,因为有的退出了
//但是在底下退出的时候并没有修改_cliens_change为true
//如果客户端数量不改变,就不用每次都查询socket再添加,而是直接将已经添加的客户端复制
//到拷贝区
if (_clients_change)
{
_maxSock = _clients.begin()->second->sockfd();
for (auto iter:_clients)
{
FD_SET(iter.second->sockfd(),&fdRead);
if (_maxSock < iter.second->sockfd())
{
_maxSock = iter.second->sockfd();
}
}
//将新增的客户端备份
memcpy(&_fdRead_bak, &fdRead, sizeof(fd_set));
_clients_change = false;
}
else
{
//5.把上次备份的fdread拷贝进去,上次800个这次却只有799个长度,于是循环还是按800计算,就低下的else提示溢出了
memcpy(&fdRead, &_fdRead_bak, sizeof(fd_set));
}
//&_select_wait_time
int ret = select(_maxSock + 1, &fdRead, nullptr, nullptr, nullptr);
if (ret < 0)
{
printf(" Accept Select is finish... \n ");
Close();
return false;
}
else if (ret == 0)
{
continue;
}
#ifdef _WIN32
//遍历fdread中的每个socket
for (int i = 0; i < fdRead.fd_count; i++)
{
//find找回的map的指针
auto iter = _clients.find(fdRead.fd_array[i]);
//end不是迭代器中的数据,在迭代器外,也就是迭代器终止数据的尾部
//iter=end 就意味着iter指的是一个无效数据
if (iter != _clients.end())
{
//接收数据不成功=-1。这个socket接收数据不成功就清除这个socket在map中的位置
if (-1 == RecvData(iter->second))
{
//判断这个是否为空,如果为空就不if,不为空就if
if (_pNetEvent)
{
//先leave再抹去
_pNetEvent->OnNetLeave(iter->second);
}
//1.如果_client_change=false
_clients_change = true;
_clients.erase(iter->first);
}
}else
{
printf("error.if(iter!=_clients.end())\n");
}
}
#else
//做一个记录,用一个vector承接map的第二个元素,然后再单独删除map中的第二个元素
//临时的在这个循环中,不用clean,循环结束后自动释放空间
std::vector<ClientSocket*>temp;
for (auto iter :_clients)
{
if (FD_ISSET(iter.second->sockfd(), &fdRead))
{
if (-1==RecvData(iter.second))
{
if (_pNetEvent)
_pNetEvent->OnNetLeave(iter.second);
_clients_change = true;
temp.pushback(iter.second);
}
}
}
for (auto pClient:temp )
{
//移除vector中的sock
_clients.erase(pClient->sockfd());
//删除pclient指针
delete pClient;
}
#endif // _WIN32
}
}
修改功能点
1.如果客户端数量不改变,就不用每次都查询socket再添加,而是直接将已经添加的客户端复制到拷贝区
2.客户端队列改为map增加查询效率。