34_优化server可写检测性能

基本上所有的客户端都是可写的,所有的客户端都加入到可写检测列表中,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的消耗

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top