TCP Winsock: accept multiple connections/clients

夙愿已清 提交于 2019-11-28 00:31:41

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.

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!