单线程实现TCP多端口监听服务端

背景介绍

在网络编程中,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;
}

小结

多服务端端口监听,可以使用单线程即可完成,在线程数成本上能够大量节约资源。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 C++ 中实现监听 25 端口的方式有很多,这里介绍一种基于 Winsock2 的实现方式: ```c++ #include <iostream> #include <winsock2.h> #include <thread> #pragma comment(lib, "ws2_32.lib") void handle_client(SOCKET client_socket) { // 处理客户端连接的业务逻辑 std::cout << "Client connected." << std::endl; // 关闭 socket shutdown(client_socket, SD_BOTH); closesocket(client_socket); std::cout << "Client disconnected." << std::endl; } int main() { // 初始化 Winsock2 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 2), &wsa_data); if (result != 0) { std::cerr << "WSAStartup failed: " << result << std::endl; return 1; } // 创建 socket SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == INVALID_SOCKET) { std::cerr << "Failed to create socket: " << WSAGetLastError() << std::endl; WSACleanup(); return 1; } // 绑定地址和端口 sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(25); result = bind(listen_socket, reinterpret_cast<sockaddr*>(&address), sizeof(address)); if (result == SOCKET_ERROR) { std::cerr << "Failed to bind socket: " << WSAGetLastError() << std::endl; closesocket(listen_socket); WSACleanup(); return 1; } // 监听端口 result = listen(listen_socket, SOMAXCONN); if (result == SOCKET_ERROR) { std::cerr << "Failed to listen: " << WSAGetLastError() << std::endl; closesocket(listen_socket); WSACleanup(); return 1; } std::cout << "Listening on port 25..." << std::endl; while (true) { // 接受客户端连接 SOCKET client_socket = accept(listen_socket, nullptr, nullptr); if (client_socket == INVALID_SOCKET) { std::cerr << "Failed to accept client: " << WSAGetLastError() << std::endl; closesocket(listen_socket); WSACleanup(); return 1; } // 创建新线程处理客户端连接 std::thread(handle_client, client_socket).detach(); } // 关闭 socket closesocket(listen_socket); // 清理 Winsock2 WSACleanup(); return 0; } ``` 该代码片段创建了一个监听 25 端口的 socket,然后不断地接受客户端连接,并在新线程中处理客户端连接的业务逻辑。在业务逻辑处理完毕后,关闭 socket,结束该客户端连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值