39_从server中分离出select

select相较于epoll,使用较简单,没有单独实现CELLselect.hpp文件

CELLSelectServer.hpp

#ifndef _CELLSelectServer_HPP_
#define _CELLSelectServer_HPP_

#include"CELLServer.hpp"
#include"CELLFDSet.hpp"

//网络消息接收处理服务类
class CELLSelectServer:public CELLServer
{
public:
    ~CELLSelectServer()
    {
        Close();
    }
    bool DoNetEvents()
    {
        //计算可读集合
        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)
        {
            if(errno == EINTR)
            {
                CELLLog_Info("CELLSelectServer select EINTR");
                return true;
            }
            CELLLog_PError("CELLSelectServer%d.OnRun.select", _id);
            return false;
        }
        else if (ret == 0)
        {
            return true;
        }
        ReadData();
        WriteData();
        return true;
    }

    void WriteData()
    {
#ifdef _WIN32
        auto pfdset = _fdWrite.fdset();
        for (int n = 0; n < pfdset->fd_count; n++)
        {
            auto iter = _clients.find(pfdset->fd_array[n]);
            if (iter != _clients.end())
            {
                if (SOCKET_ERROR == iter->second->SendDataReal())
                {
                    OnClientLeave(iter->second);
                    _clients.erase(iter);
                }
            }
        }

#else
        for (auto iter = _clients.begin(); iter != _clients.end(); )
        {
            if (iter->second->needWrite() && _fdWrite.has(iter->second->sockfd()))
            {
                if (SOCKET_ERROR == iter->second->SendDataReal())
                {
                    OnClientLeave(iter->second);
                    auto iterOld = iter;
                    iter++;
                    _clients.erase(iterOld);
                    continue;
                }
            }
            iter++;
        }
#endif
    }

    void ReadData()
    {
#ifdef _WIN32
            auto pfdset = _fdRead.fdset();
            for (int n = 0; n < pfdset->fd_count; n++)
            {
                auto iter = _clients.find(pfdset->fd_array[n]);
                if (iter != _clients.end())
                {
                    if (SOCKET_ERROR == RecvData(iter->second))
                    {
                        OnClientLeave(iter->second);
                        _clients.erase(iter);
                    }
                }
            }
#else
            for (auto iter = _clients.begin(); iter != _clients.end(); )
            {
                if (_fdRead.has(iter->second->sockfd()))
                {
                    if (SOCKET_ERROR == RecvData(iter->second))
                    {
                        OnClientLeave(iter->second);
                        auto iterOld = iter;
                        iter++;
                        _clients.erase(iterOld);
                        continue;
                    }
                }
                iter++;
            }
#endif
    }

private:
    //伯克利套接字 BSD socket
    //描述符(socket) 集合
    CELLFDSet _fdRead;
    CELLFDSet _fdWrite;
    //备份客户socket fd_set
    CELLFDSet _fdRead_bak;
    //
    SOCKET _maxSock;
};

#endif // !_CELLSelectServer_HPP_

EasySelectServer.hpp

#ifndef _EasySelectServer_hpp_
#define _EasySelectServer_hpp_

#include"EasyTcpServer.hpp"
#include"CELLSelectServer.hpp"
#include"CELLFDSet.hpp"

class EasySelectServer : public EasyTcpServer
{
public:
    void Start(int nCELLServer)
    {
        EasyTcpServer::Start<CELLSelectServer>(nCELLServer);
    }
protected:
    //处理网络消息
    void OnRun(CELLThread* pThread)
    {
        //伯克利套接字 BSD socket
        //描述符(socket) 集合
        CELLFDSet fdRead;
        while (pThread->isRun())
        {
            time4msg();
            //清理集合
            fdRead.zero();
            //将描述符(socket)加入集合
            fdRead.add(sockfd());
            ///nfds 是一个整数值 是指fd_set集合中所有描述符(socket)的范围,而不是数量
            ///既是所有文件描述符最大值+1 在Windows中这个参数可以写0
            timeval t = { 0, 1};
            int ret = select(sockfd() + 1, fdRead.fdset(), 0, 0, &t); //
            if (ret < 0)
            {
                if(errno == EINTR)
                {
                    CELLLog_Info("EasySelectServer select EINTR");
                    continue;
                }

                CELLLog_PError("EasySelectServer.OnRun select.");
                pThread->Exit();
                break;
            }
            //判断描述符(socket)是否在集合中
            if (fdRead.has(sockfd()))
            {
                //fdRead.del(_sock);
                Accept();
            }
        }
    }
};

#endif // !_EasySelectServer_hpp_

Leave a Comment

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

Scroll to Top