大数跨境
0
0

03. 一个连接一个线程模型介绍

03. 一个连接一个线程模型介绍 CppGuide
2024-01-18
2

关注我,更多的优质内容第一时间阅读


正因为最原始的服务器结构不支持并发,随着计算机引入多线程模型后,软件开发者想出了另外一种服务器结构,即给每一个客户端连接创建一个线程,这样多个线程就可以并行执行了,可以同时为多个客户端服务。

示例代码如下:

//侦听线程
UINT WINAPI MyMainThread(LPVOID lPvoid)
{
    LOG_NORMAL("Start MyMainThread successfully, ThreadID = %u.", ::GetCurrentThreadId());
    
    UINT  nThreadID = 0;
    SOCKET  sListenSocket = (SOCKET)lPvoid;
    SOCKET  sClientSocket = 0;
    while (1)
    {
        //等待客户连接
        sockaddr_in clientAddr = { 0 };
        int clientAddrLength = sizeof(clientAddr);
        if ((sClientSocket = accept(sListenSocket, (struct sockaddr*)&clientAddr, &clientAddrLength)) == INVALID_SOCKET)
            break;

        LOG_NORMAL("New client connected: %s:%d", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

        //启动客户签到线程
        _beginthreadex(NULL, 0, MyChildThread, (LPVOID)sClientSocket, 0, &nThreadID);
    }

    closesocket(sListenSocket);
    return 0;
}
//接收连接线程
UINT WINAPI MyChildThread(LPVOID lPvoid)
{
    LOG_NORMAL("Start MyChildThread successfully, ThreadID = %u.", ::GetCurrentThreadId());
    
    //交易处理
    SOCKET sClientSocket = (SOCKET)lPvoid;
    CLIENTITEM clientItem = { 0 };
    int nCmd = HandleClientMain(sClientSocket, &clientItem);

    LOG_NORMAL("Client cmd = %d", nCmd);
    if (nCmd == -1)
        closesocket(sClientSocket);
    else if (nCmd == CONN_MAIN)
        LoginTrans(sClientSocket, &clientItem);
    else
        InterTrans(sClientSocket, &clientItem, nCmd);
    return 0;
}

上述代码中,在某个线程 MyMainThread 中(可以是主线程也可以是非主线程)调用 accept 接受客户端连接,成功接受连接后,为每一个新连接创建一个工作线程(MyChildThread)。当然,为了能让工作线程可以正常处理所负责的连接上的来往数据,利用线程函数参数将 socket 句柄传给工作线程(注意上述代码中参数 sClientSocket 的传递方法)。

正文完。


相关阅读


小方目前在一家知名外企做 C++ 架构方面的工作。我建立 高质量 C++ 后端开发微信技术交流群,群里高手如云,不定期分享编程技术,也会提供一些求职和内推资源。


现在限时开放中,需要加群交流的同学可以加微信 cppxiaofang,备注“加群”。


关注我,更多的优质内容第一时间阅读

【声明】内容源于网络
0
0
CppGuide
专注于高质量高性能C++开发,站点:cppguide.cn
内容 1260
粉丝 0
CppGuide 专注于高质量高性能C++开发,站点:cppguide.cn
总阅读289
粉丝0
内容1.3k