Linux网络编程 8 - 重构后的select模式的Tcpserver

完整实现代码:https://download.csdn.net/download/k117470154/10520499

1. socket_tcpserver_select.h

#ifndef _SOCKET_TCPSERVER_SELECT_H
#define _SOCKET_TCPSERVER_SELECT_H

#include "socket_tcpserver.h"

/* 单线程 select 非阻塞 */
class CTcpServer_select : public CTcpSvrApp
{
public:
    CTcpServer_select(STRCPP svrip, WORD16 svrport) : CTcpSvrApp(svrip, svrport) {}
    virtual VOID initreqtype()
    {
        m_reqtype = new CTcpSvrReq(m_ip, m_port, FALSE);
    }
    virtual VOID working();      // socket处理函数
    virtual VOID select_fdset(); // 设置select使用的参数
    virtual VOID select_self();  // 本端socket可读时的处理函数
    virtual VOID select_peer();  // 对端socket可读时的处理函数
protected:
    SOCKFD      m_maxfd;    // select使用的maxfd参数
    fd_set      m_readset;  // select使用的可读fdset
    TIMEVAL     m_timeval;  // select使用的timeval参数
};

#endif

2. socket_tcpserver_select.cpp

#include "socket_tcpserver_select.h"

/* 单线程多连接 非阻塞 */
VOID CTcpServer_select::working()
{    
    SWORD32 ret = 0;

    while(NULL != m_reqtype)
    {
        m_timeval.tv_sec  = 1;   // 超时时间1秒
        m_timeval.tv_usec = 0;

        select_fdset();

        ret = select(m_maxfd+1, &m_readset, NULL, NULL, &m_timeval);
        if(ret < 0)
        {
            cout << "CTcpServer_select selcet failed, errno:" << errno << endl;
            break;
        }
        else if(0 == ret)   // 没有可读的socket
        {
            continue;
        }
        else
        {
            select_self();
            select_peer();
        }
    }
}

/* 获取maxfd */ 
VOID CTcpServer_select::select_fdset()
{
    SOCKFD peerfd = INVALIDFD;
    SOCKFD selffd = INVALIDFD;
    
    FD_ZERO(&m_readset);
    for(REQUESTITER it = m_requests.begin(); it != m_requests.end(); ++it)
    {
        CTcpSvrReq* req = (CTcpSvrReq*)(*it);
        peerfd = req->peerfd();
        if(NULL != req)
        {
            peerfd = req->peerfd();
            if(INVALIDFD != peerfd)
            {
                FD_SET(peerfd, &m_readset);
                m_maxfd = peerfd > m_maxfd ? peerfd : m_maxfd;
            }
        }
    }

    if(NULL != m_reqtype)
    {
        selffd = m_reqtype->selffd();
        if(INVALIDFD != selffd)
        {
            FD_SET(selffd, &m_readset);
            m_maxfd = selffd > m_maxfd ? selffd : m_maxfd;
        }
    }
}

// 如果本端socket可读 则是有客户端发起连接 调用accept函数(重构后activate) 接受连接
VOID CTcpServer_select::select_self()
{
    SOCKFD fd = m_reqtype->selffd();
    if(INVALIDFD != fd && FD_ISSET(fd, &m_readset))
    {
        CTcpSvrReq* req = (CTcpSvrReq*)m_reqtype->clone();
        if(NULL != req)
        {
            if(req->activate())
            {
                m_requests.push_back(req);
            }
            else
            {
                cout << "CTcpServer_select activate failed" << endl;
                delete req;
            }
        }
        else
        {
            cout << "CTcpServer_select clone failed" << endl;
        }
    }

}

// 如果对端socket可读 则是有客户端发来数据 调用receive接收成功后 再调用process处理数据
VOID CTcpServer_select::select_peer()
{
    for(REQUESTITER it = m_requests.begin(); it != m_requests.end();)
    {
        CTcpSvrReq* req = (CTcpSvrReq*)(*it);
        if(NULL != req)
        {
            if(INVALIDFD != req->peerfd())
            {
                if(FD_ISSET(req->peerfd(), &m_readset) && req->receive())
                {
                    req->process();
                }
            }
            else
            {
                delete req;
                it = m_requests.erase(it);
                continue;
            }
        }
        ++it;
    }
}

猜你喜欢

转载自blog.csdn.net/k117470154/article/details/82750245