简体   繁体   中英

TCP Winsock: accept multiple connections/clients

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.

while(true)
{
    if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
    {
        for(int i = 0; i < MaxUsers; i++)
        {
            if(!ClientAddress[i].sin_family)
            {
                ClientAddress[i] = IncomingAddress;
                char Version[128], Dir[256], Path[256], URL[128], Message[256];
                GetCurrentDirectory(256, Dir);
                sprintf(Path, "%s\\Version.ini", Dir);
                GetPrivateProfileString("Default", "Version", "1.0.0.0", Version, 128, Path);
                GetPrivateProfileString("Default", "URL", "", URL, 128, Path);
                GetPrivateProfileString("Default", "Message", "", Message, 256, Path);
                send(Sub, Version, 128, 0);
                send(Sub, Message, 256, 0);
                break;
            }
        }
        continue;

    }
}

Of course new clients cannot be accepted because the server handles just accepted client, ie 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM