完整实现代码: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;
}
}