Windows7下C语言编写的TCP客户端遇Socket error 10054(Connection reset by peer)及服务器netstat无监听端口问题求助
问题分析与解决建议
让我帮你拆解一下问题的根源,你的服务器和客户端代码里存在几个关键错误,直接导致了当前的现象:
1. 服务器端accept语句的运算符优先级错误(核心问题)
看服务器代码里的这一行:
if (client_socket = accept(server_socket, NULL, NULL) == INVALID_SOCKET)
C语言中==的优先级高于=,所以这行代码的实际执行逻辑是:
- 先判断
accept(server_socket, NULL, NULL)的返回值是否等于INVALID_SOCKET - 把这个判断的布尔结果(0或1)赋值给
client_socket
这就导致client_socket拿到的根本不是有效的客户端套接字,而是一个无效的数值。后续的send操作其实是在一个无效套接字上执行的(虽然你的服务器代码没检查send的返回值,所以误以为发送成功),而且服务器在执行完这些操作后直接关闭了监听套接字并退出,客户端的连接因此被重置,触发了10054错误。
修复方法:给赋值表达式加上括号,确保先执行赋值再判断:
if ((client_socket = accept(server_socket, NULL, NULL)) == INVALID_SOCKET)
2. 服务器端send函数的参数错误
你的服务器代码中发送消息的语句:
send(client_socket, server_message, sizeof(server_message), 0);
sizeof(server_message)获取的是指针的大小(32位系统是4字节,64位是8字节),而不是字符串的实际长度。这会导致只发送了字符串的前几个字符,甚至可能发送不完整。
修复方法:使用strlen获取字符串长度,加上1以包含字符串终止符\0:
char *server_message = "You have reached the server!"; int send_len = strlen(server_message) + 1; if (send(client_socket, server_message, send_len, 0) == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); }
同时建议加上send的返回值检查,避免出现隐性错误。
3. 服务器生命周期问题(导致netstat看不到监听)
当前服务器处理完一个连接(哪怕是错误的连接)后,直接关闭监听套接字并退出程序。当你运行netstat命令时,服务器已经停止运行了,自然看不到9002端口的监听状态。
修复方法:把连接处理逻辑放到循环中,让服务器持续监听新连接,并且只关闭客户端套接字,保留监听套接字:
// 在listen之后添加循环 while (1) { puts("Waiting for incoming connections..."); SOCKET client_socket = accept(server_socket, NULL, NULL); if (client_socket == INVALID_SOCKET) { printf("Error accepting connections: %d\n", WSAGetLastError()); continue; } puts("Connection accepted!"); // 发送消息 char *server_message = "You have reached the server!"; int send_len = strlen(server_message) + 1; if (send(client_socket, server_message, send_len, 0) == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); } else { puts("Message sent!"); } // 关闭客户端套接字,而非监听套接字 closesocket(client_socket); } // 只有当程序退出循环时才关闭监听套接字 closesocket(server_socket);
这样服务器会一直处于监听状态,此时运行netstat -ano | findstr :9002就能看到9002端口处于LISTENING状态了。
4. 客户端代码的优化建议
- 客户端的
recv操作没有处理字符串终止符,可能导致输出乱码,建议添加终止符:char buffer[256]; int recv_len = recv(network_socket, buffer, sizeof(buffer) - 1, 0); if (recv_len == SOCKET_ERROR) { printf("Receive error: %d\n", WSAGetLastError()); WSACleanup(); return EXIT_FAILURE; } buffer[recv_len] = '\0'; // 添加字符串终止符 printf("The server sent the data: %s\n", buffer); - 代码中同时使用了
inet_addr和inet_pton设置服务器地址,属于冗余操作,建议保留更安全的inet_pton即可,删除server_address.sin_addr.s_addr = inet_addr("127.0.0.1");这一行。
验证步骤
- 修复服务器代码的上述错误后重新编译运行
- 当服务器显示
Waiting for incoming connections...时,打开命令提示符运行netstat -ano | findstr :9002,确认端口处于监听状态 - 运行客户端程序,此时应该能正常接收服务器发送的消息,不再出现
10054错误
内容的提问来源于stack exchange,提问作者Leonardo Araujo
相关产品推荐
相关产品推荐

