【问题标题】:Improve server to deal with multiple clients改进服务器以处理多个客户端
【发布时间】:2015-02-24 14:33:25
【问题描述】:

我正在尝试创建一个与 2 个客户端通信的服务器,每次 1 个。与一个客户端通话后,服务器向两个客户端发送消息。 我找到了一个服务器的基本代码,我尝试升级它以接受多个连接,我看到了两种方式:线程,或者做套接字数组,但我无法理解。 有人可以解释一下如何使用线程并举个例子吗? 这是代码:

int main()
{
    WSADATA WsaDat;
    if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0)
    {
        std::cout << "WSA Initialization failed!\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (Socket == INVALID_SOCKET)
    {
        std::cout << "Socket creation failed.\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    SOCKADDR_IN serverInf;
    serverInf.sin_family = AF_INET;
    serverInf.sin_addr.s_addr = INADDR_ANY;
    serverInf.sin_port = htons(8888);

    if (bind(Socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
    {
        std::cout << "Unable to bind socket!\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    listen(Socket, 1);

    SOCKET TempSock = SOCKET_ERROR;
    while (TempSock == SOCKET_ERROR)
    {
        std::cout << "Waiting for incoming connections...\r\n";
        TempSock = accept(Socket, NULL, NULL);
    }

    // If iMode!=0, non-blocking mode is enabled.
    u_long iMode = 1;
    ioctlsocket(Socket, FIONBIO, &iMode);

    Socket = TempSock;
    std::cout << "Client connected!\r\n\r\n";

    // Main loop
    for (;;)
    {
        char *szMessage = "Welcome to the server!\r\n";
        send(Socket, szMessage, strlen(szMessage), 0);

        int nError = WSAGetLastError();
        if (nError != WSAEWOULDBLOCK&&nError != 0)
        {
            std::cout << "Winsock error code: " << nError << "\r\n";
            std::cout << "Client disconnected!\r\n";

            // Shutdown our socket
            shutdown(Socket, SD_SEND);

            // Close our socket entirely
            closesocket(Socket);

            break;
        }

        Sleep(1000);
    }

    WSACleanup();
    system("PAUSE");
    return 0;
}

【问题讨论】:

    标签: c++ multithreading server


    【解决方案1】:

    为此,您需要一个服务器套接字和一个 clientsocket 数组,如下所示:

    服务器:

    ACCEPT:
    int clientsock[2];
    minsocks = 0;
    numsocks = 2;
    while(minsock < numsocks)
    {
        clientsock[minsock] = accept(serversock,
        (struct sockaddr *) &clientaddr,
        (socklen_t *)&clientaddrlen);
        minsock++;
    }
    
    
    RECIEVE:
    
    
    char message[6];
    int data;
    int limit = 6;
    for(int i = 0; i < NUMSOCK; i++)
    {
        int in = recv(clientsock[i], &message[index], limit, 0);
        if(in > 0)
        {
            index += in;
            limit -= in;
        }
        else if ( in == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
    }
    

    这对您来说应该是一个好的开始。

    线程 - C 版本

    pthread_t sniffer_thread;
    if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
        {
            perror("could not create thread");
            return 1;
        }
    
        //Now join the thread , so that we dont terminate before the thread
        //pthread_join( sniffer_thread , NULL);
        puts("Handler assigned");
     }
    
    /*
     * This will handle connection for each client
     * */
    void *connection_handler(void *socket_desc)
    {
        //Get the socket descriptor
        int sock = *(int*)socket_desc;
        int read_size;
        char *message , client_message[2000];
        while(in != 0)
        {
            int in = recv(socket_desc, &client_message[index], limit, 0);
            if(in > 0)
            {
                 index += in;
                 limit -= in;
            }
            else
                printf("recv failed: %d\n", WSAGetLastError());   
        }
        //Free the socket pointer
        free(socket_desc);
    
        return 0;
    }
    

    【讨论】:

    • 这是一个好的开始,而且还有很多空间可以添加和改进。
    • 你能举个例子说明我可以在这里添加或改进什么吗?
    • 首先是更多的客户端,更安全的 if 语句和 aslo 通常可以有多个消息缓冲区和更好的客户端代码。
    • 此代码是一个通用模板,您可以在其中改进以进行编程
    • 我认为就我而言,我只需要 1 个缓冲区。你能给我一个需要超过 1 个缓冲区的例子吗?我什么时候需要线程?感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 2011-01-01
    相关资源
    最近更新 更多