背景介绍
在网络编程中,CS模式是常见的场景,独立监听端口对应独立接收线程。
扩展要求
当需要监听多个(大于1个)端口时,也会采用多个监听线程
再拓展要求
当需要监听10000个端口,如监听端口区间[10001,20000],启动10000个监听线程?
这明显是不合理的。
伪代码实现
class MultiPortListener {
public:
int32_t RegisterServer(int32_t port);
int32_t StartUp();
private:
int32_t AddNode(const int32_t iFd, const uint16_t uPort);
int32_t QryNode(const int32_t iFd, uint16_t &uPort);
int32_t DelNode(const int32_t iFd, const uint16_t uPort);
private:
Array<Node> *_pArray;
TcpServer **_SockSvr;
Epoll *_listenEpoll;
}
int32_t MultiPortListener::RegisterServer(int32_t port) {
uint16_t uPort = port;
if (_SockSvr[uPort]) {
DelNode(_SockSvr[uPort]->GetSockFd(), uPort);
_SockSvr[uPort]->Close();
delete _SockSvr[uPort]; }
_SockSvr[uPort] = new TcpServer();
int32_t iRet = _SockSvr[uPort]->Init(uPort);
if (0 != iRet) {
return -1;
}
//将监听的socket和epoll进行绑定
struct epoll_event epv = {0, {0}};
epv.events = EPOLLIN;
epv.data.fd = _SockSvr[uPort]->GetSockFd();
iRet = _listenEpoll->EpollCtrl(NS_EPOLLBASE::ENUM_EPOLL_ADD, &epv);
if (0 != iRet) {
return -1;
}
if (0 != AddNode(_SockSvr[uPort]->GetSockFd(), uPort)) {
return -1;
}
}
int32_t MultiPortListener::StartUp() { //for create_thread to run
struct epoll_event *pEpollEvents = _listenEpoll->GetEpollEvents();
int32_t iSockFd = -1;
uint16_t uPort = 0;
while (1) {
int32_t iEventNum = _listenEpoll->EpollWait();
for (int32_t i = 0; i < iEventNum; i++) {
if (0 == QryNode(pEpollEvents[i].data.fd, uPort)) {
if (pEpollEvents[i].events & EPOLLIN) {
while ((iSockFd = _SockSvr[uPort]->GetConnection()) >= 0) {
//TODO process the clientfd for business
}
} else //TODO do some thing else if not EPOLLIN event
}
}
return 0;
}
小结
多服务端端口监听,可以使用单线程即可完成,在线程数成本上能够大量节约资源。