0

我已经使用带有 CreateThread() 方法的 WINAPI 编写了一个服务器。第一个连接请求总是终止。以下所有请求/线程都按预期工作。我不知道为什么,所以我希望有人能告诉我。这是一个说明问题的工作示例。

DWORD WINAPI process_thread(LPVOID lpParam) {

    SOCKET current_client = (SOCKET)lpParam;
    char buf[1024];
    int res;

    while(1) {

        res = recv(current_client, buf, strlen(buf), 0);            
        if(res>0) {
            buf[res] = '\0';
            send(current_client, buf, strlen(buf), 0);
        }

    }
}

int main() {

    SOCKET sock;
    DWORD thread;    
    WSADATA wsaData;    
    SOCKADDR_IN server;

    WSAStartup(0x102,&wsaData);

    server.sin_family=AF_INET;
    server.sin_addr.s_addr=INADDR_ANY;
    server.sin_port=htons(123);

    sock=socket(AF_INET,SOCK_STREAM,0);    
    bind(sock,(SOCKADDR*)&server,sizeof(server));    
    listen(sock,5);

    SOCKET client;    
    SOCKADDR_IN from;
    int fromlen = sizeof(from);

    while(1) {

        client = accept(sock,(struct SOCKADDR*)&from,&fromlen);       
        CreateThread(NULL, 0,process_thread,(LPVOID)client, 0, &thread);

    }

    closesocket(sock);
    WSACleanup();

    return 0;

}
4

1 回答 1

1

strlen()您在线程代码中滥用。

调用时recv(),您需要指定缓冲区的完整大小。 strlen()不是获得该价值的正确方法。改为使用sizeof()

然后,当recv()退出时,它的返回值告诉你确切知道缓冲区中有多少字节是有效的。同样,strlen()这不是获得该价值的正确方法。

此外,您不需要仅仅将缓冲区传递给send(). 由于您被告知缓冲区中有多少字节,因此只需发送那么多字节。

此外,当客户端与服务器断开连接时,您的线程不会终止或关闭其套接字。

此外,您main()正在泄漏线程句柄,并且根本没有进行任何类型的错误处理。

尝试更多类似的东西:

bool sendAll(SOCKET sock, void *buf, int buflen)
{
    char *ptr = (char*) buf;
    int sent;

    while (buflen > 0) {
        sent = send(sock, ptr, buflen, 0);
        if (sent == SOCKET_ERROR) {
            return false;
        }
        ptr += sent;
        buflen -= sent;
    }

    return true;
}

DWORD WINAPI process_thread(LPVOID lpParam) {

    SOCKET client = (SOCKET) lpParam;
    char buf[1024], *ptr;
    int recvd;

    do {
        recvd = recv(client, buf, sizeof(buf), 0);            
        if (recvd <= 0) {
            break;
        }
        if (!sendAll(client, buf, recvd)) {
            break;
        }
    }
    while (true);

    closesocket(client);
    return 0;
}

int main() {

    WSADATA wsaData;
    SOCKET server, client;
    SOCKADDR_IN serveraddr;
    SOCKADDR_IN clientaddr;
    int res, clientaddrlen;
    HANDLE hThread;
    DWORD threadID;

    res = WSAStartup(MAKEWORD(2, 1), &wsaData);
    if (res != 0) {
        return 1;
    }

    ZeroMemory(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_port = htons(123);

    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == INVALID_SOCKET) {
        WSACleanup();
        return 1;
    }

    res = bind(server, (SOCKADDR*) &serveraddr, sizeof(serveraddr));
    if (res == SOCKET_ERROR) {
        closesocket(server);
        WSACleanup();
        return 1;
    }

    res = listen(server, 5);
    if (res == SOCKET_ERROR) {
        closesocket(server);
        WSACleanup();
        return 1;
    }

    do {
        clientaddrlen = sizeof(clientaddr);

        client = accept(server, (SOCKADDR*) &clientaddr, &clientaddrlen);
        if (client == INVALID_SOCKET) {
            closesocket(server);
            WSACleanup();
            return 1;
        }

        hThread = CreateThread(NULL, 0, process_thread, (LPVOID) client, 0, &threadID);
        if (hThread)
            CloseHandle(hThread);
        else
            closesocket(client);
    }
    while (true);

    closesocket(server);
    WSACleanup();

    return 0;
}
于 2018-12-15T00:42:22.743 回答