TCP Winsock: accept multiple connections/clients

前端 未结 2 1915
梦毁少年i
梦毁少年i 2020-12-06 08:28

I tried to can multiply clients, and send it to each one. But it working only for one, after one client connected the server just useless for incoming connections.



        
相关标签:
2条回答
  • 2020-12-06 09:09

    After accepting socket create separate thread for client requests. Then continue wait for new accepting.

    For example:

        ...
        while (1)
        {
            AcceptSocket = SOCKET_ERROR;
    
            while (AcceptSocket == SOCKET_ERROR )
            {
                AcceptSocket = accept( m_socket, NULL, NULL );
            }
    
            printf( "Client Connected.\n");
    
            DWORD dwThreadId;
            CreateThread (NULL, 0, ProcessClient, (LPVOID) AcceptSocket, 0, &dwThreadId);
        }
        ...
    

    Where ProcessClient function could be like this:

    DWORD WINAPI ProcessClient (LPVOID lpParameter)
    {
        SOCKET AcceptSocket = (SOCKET) lpParameter;
    
        // Send and receive data.
        int bytesSent;
        int bytesRecv = SOCKET_ERROR;
        char sendbuf[2000]="";
        char recvbuf[2000]="";
    
        char timebuf[128];
    
        sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", ipaddr, port);
        bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
    
        if (bytesSent == SOCKET_ERROR)
        {
            printf( "Error at send hello: %ld\n", WSAGetLastError());
            goto fin;
        }
    
        while (1)
        {
            _strtime( timebuf );
            ZeroMemory (recvbuf, sizeof(recvbuf));
    
            bytesRecv = recv( AcceptSocket, recvbuf, 32, 0);
            printf( "%s Client said: %s\n", timebuf, recvbuf);
    
            if (strcmp(recvbuf, "1") == 0)
            {
                sprintf(sendbuf, "You typed ONE\n");
                //printf("Sent '%s'\n", sendbuf);
                bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
    
                if (bytesSent == SOCKET_ERROR)
                {
                    printf( "Error at send: %ld\n", WSAGetLastError());
                    goto fin;
                }
            }
            else if (strcmp(recvbuf, "2") == 0)
            {
                sprintf(sendbuf, "You typed TWO\n");
                //printf("Sent '%s'\n", sendbuf);
                bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
    
                if (bytesSent == SOCKET_ERROR)
                {
                    printf( "Error at send: %ld\n", WSAGetLastError());
                    goto fin;
                }
            }
            else if (strcmp(recvbuf, "exit") == 0)
            {
                printf( "Client has logged out\n", WSAGetLastError());
                goto fin;
            }
            else
            {
                sprintf(sendbuf, "unknown command\n");
                //printf("Sent '%s'\n", sendbuf);
                bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
    
                if (bytesSent == SOCKET_ERROR)
                {
                    printf( "Error at send: %ld\n", WSAGetLastError());
                    goto fin;
                }
            }
        }
    
    fin:
        printf("Client processed\n");
    
        closesocket(AcceptSocket);
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-06 09:20

    Of course new clients cannot be accepted because the server handles just accepted client, i.e. the server is busy.

    The solution is simple: create a new thread for each accepted client and handle the client session there. Just use _beginthreadex() (#include <process.h>):

    unsigned __stdcall ClientSession(void *data)
    {
        SOCKET client_socket = (SOCKET)data;
        // Process the client.
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        ...
    
        SOCKET client_socket;
        while ((client_socket = accept(server_socket, NULL, NULL))) {
            // Create a new thread for the accepted client (also pass the accepted client socket).
            unsigned threadID;
            HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)client_socket, 0, &threadID);
        }
    }
    

    By the way, send()/recv() functions do not guarantee that all the data would be sent/received at one call. Please see the documentation for return value of these functions.

    0 讨论(0)
提交回复
热议问题