c-Winsock服务器使用WinAPI线程重置第一个连接



我已经用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] = '';
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()而终止缓冲区。由于您被告知缓冲区中有多少字节,所以只需发送那么多字节即可。

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

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

最新更新