繁体   English   中英

Winsock Server使用WinAPI线程重置优先连接

[英]Winsock Server using WinAPI Thread reset first connection

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

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;

}

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

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

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

另外,您无需将缓冲区传递给send()就可以使缓冲区以null终止。 由于您被告知缓冲区中有多少字节,因此只需发送那么多字节即可。

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

另外,您的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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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