【问题标题】:Winsock threaded server does not work well when multiple clients connect?Winsock线程服务器在多个客户端连接时不能正常工作?
【发布时间】:2012-12-17 04:08:35
【问题描述】:

我有一个服务器,它为连接到它的每个客户端生成一个线程。然后线程处理向客户端接收/发送数据。这是我的服务器代码:

    //////////////
    //  START   //
    /////////////
    while( 1 )
    {
    if( listen(serverSocket, SOMAXCONN) == SOCKET_ERROR ) 
    {
        printf( "Listen failed with error: %ld\n", WSAGetLastError() );
        break;
    }    
        /*
         *  wait for clients...
        */
        clientSocket = accept(serverSocket,
                              (struct sockaddr *)&clientSockAddr,
                              &clientSockAddrLen);


        if( clientSocket == INVALID_SOCKET )
        {
            printf("%d:accept failed\n", WSAGetLastError());
            closesocket(serverSocket);
            WSACleanup();
            return 1;
        }

        printf("Client accepted: IP: %s PORT: %d\n",
            inet_ntoa(clientSockAddr.sin_addr),
            clientSockAddr.sin_port );

        THREADDATA threadData = { clientSocket };
        sprintf_s(threadData.ip, "%s", inet_ntoa(clientSockAddr.sin_addr));

        // spawn a thread for each client
        hthread = CreateThread(
                    NULL,                       // don't inherit handle
                    0,                          // use default size for the executable
                    processClient,
                    (pTHREADDATA)&threadData,   // thread data
                    0,                          // run right away
                    &threadId );
    }

这是我的线程函数的样子:

/*
    called by thread for each client
*/
DWORD WINAPI processClient(LPVOID lpParam)
{
    int numBytesRecvd = 0,
        numBytesSent = 0,
        index = 0,
        nLeft = SIZE,
        TOTAL = SIZE;

    char buff[SIZE];
    int run = 1;

    char msg[MSG_SIZE];

    pTHREADDATA td = (pTHREADDATA)lpParam;

    /* keep processing client */
    while (run)
    {
        memset(buff, 0, SIZE);

        numBytesRecvd = recv(td->clientSocket, buff, nLeft, 0);


        /* CLIENT EXITED */
        if( !strcmp(buff, "exit") )
        {

            printf("Client exited!\n");

            run = 0;
        }

        if( numBytesRecvd > 0 )
        {

            printf("< %s\n", buff);

        }

        if (numBytesRecvd == 0)
        {
            printf("Client closed!\n");
            run = 0;
        }

        if( numBytesRecvd == SOCKET_ERROR )
        {
            printf("%d:Recieve error!\n", WSAGetLastError());
            run = 0;
        }
    }

    closesocket(td->clientSocket);
    ExitThread(0);

    return 0;
}

问题:

所以我启动了服务器和客户端,比如 client1(从 win 7 中的命令提示符),一切都很好。当我在 client1 终端输入内容时,它会在服务器终端打印。

现在我启动另一个客户端 client2,它连接到服务器,并且我输入的任何内容都会显示在服务器上,但是现在当我在 client1 上输入内容时,它不会显示在服务器终端上。

所以基本上每次我启动一个新客户端时,只有那个客户端可以与服务器通信,旧客户端不能!!!但我认为线程会继续处理每个客户端?还是windows中的cmd提示符不是线程安全的?

【问题讨论】:

    标签: multithreading thread-safety winsock createthread


    【解决方案1】:

    我可以在这里看到两个可能的问题:1)您正在将堆栈上的 threadData 传递给不同的线程。您应该在堆上分配它,然后将其传递给线程。 2)我认为您没有将clientSocket正确分配给threadData,您不应该分配给threadData结构的成员吗?

    【讨论】:

    • 对不起,不同的线程是什么意思?这不就是你将数据分配给 struc 成员的方式吗??
    • 是的,但是 threadData 应该在堆上声明(因为它被传递给另一个线程),而不是在堆栈上,因为堆栈是特定于每个线程的。线程之间共享堆,而不是堆栈
    猜你喜欢
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多