Windows10+VS2015 C语言Socket服务器绑定/监听异常求助
问题排查:Socket服务器未进入等待客户端连接状态
看了你的代码,问题出在几个关键细节上,导致bind或listen执行失败,程序没走到真正等待客户端连接的accept步骤就直接结束了。我给你逐一拆解并修正:
1. Socket创建的错误判断逻辑错误
Windows下的SOCKET是无符号类型,socket()函数失败时返回的是INVALID_SOCKET(本质是(SOCKET)-1,但直接和-1比较会因为类型不匹配导致判断失效)。你原来的判断方式在Windows环境下完全起不到错误检测作用,应该改成:
if (socket_of_server == INVALID_SOCKET) { printf("creating socket failure, error code: %d\n", WSAGetLastError()); WSACleanup(); return 1; }
2. 端口设置的致命错误
你写了address_of_server.sin_port = htons(atoi(10000));,这里atoi要求传入字符串指针,但你传了整数10000,这会被当成一个内存地址去读取,大概率触发非法访问或者得到完全错误的端口值,直接导致bind失败。其实根本不需要用atoi,直接写端口数值即可:
address_of_server.sin_port = htons(10000);
3. 未检查bind和listen的返回值
bind()和listen()执行失败时都会返回SOCKET_ERROR,如果这两步失败,后续的accept()也会直接失败,程序会跳过等待逻辑直接走到WSACleanup()然后退出。必须加上错误检查和终止逻辑:
if (bind(socket_of_server, (struct sockaddr*)&address_of_server, sizeof(address_of_server)) == SOCKET_ERROR) { printf("bind failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; } if (listen(socket_of_server, 5) == SOCKET_ERROR) { printf("listen failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; }
4. 补充accept后的基础逻辑(可选但建议)
就算accept成功,你的原程序也会直接退出,建议加上客户端连接提示和简单的消息处理,方便验证:
socket_of_client = accept(socket_of_server, (struct sockaddr*)&address_of_client, &size_of_address_of_client); if (socket_of_client == INVALID_SOCKET) { printf("accept failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; } printf("Client connected from: %s:%d\n", inet_ntoa(address_of_client.sin_addr), ntohs(address_of_client.sin_port)); // 简单接收客户端消息示例 char buffer[1024]; int recv_len = recv(socket_of_client, buffer, sizeof(buffer)-1, 0); if (recv_len > 0) { buffer[recv_len] = '\0'; printf("Received from client: %s\n", buffer); } // 关闭客户端socket closesocket(socket_of_client);
修正后的完整代码
#include <stdio.h> #include <winsock2.h> #include <stdlib.h> // 为了atoi(如果需要的话) int main(int argc, char *argv[]) { WSADATA wsaData; struct sockaddr_in address_of_server; struct sockaddr_in address_of_client; int socket_of_client; int size_of_address_of_client = sizeof(address_of_client); if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) { printf("winsock initialization success\n"); } else { printf("winsock initialization failure\n"); return 1; } SOCKET socket_of_server = socket(AF_INET, SOCK_STREAM, 0); if (socket_of_server == INVALID_SOCKET) { printf("creating socket failure, error code: %d\n", WSAGetLastError()); WSACleanup(); return 1; } else { printf("creating socket success\n"); } memset(&address_of_server, 0, sizeof(address_of_server)); address_of_server.sin_family = AF_INET; address_of_server.sin_addr.s_addr = htonl(INADDR_ANY); address_of_server.sin_port = htons(10000); // 修正端口设置 // 检查bind结果 if (bind(socket_of_server, (struct sockaddr*)&address_of_server, sizeof(address_of_server)) == SOCKET_ERROR) { printf("bind failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; } printf("bind success\n"); // 检查listen结果 if (listen(socket_of_server, 5) == SOCKET_ERROR) { printf("listen failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; } printf("listen success, waiting for client connection...\n"); socket_of_client = accept(socket_of_server, (struct sockaddr*)&address_of_client, &size_of_address_of_client); if (socket_of_client == INVALID_SOCKET) { printf("accept failure, error code: %d\n", WSAGetLastError()); closesocket(socket_of_server); WSACleanup(); return 1; } printf("Client connected from: %s:%d\n", inet_ntoa(address_of_client.sin_addr), ntohs(address_of_client.sin_port)); // 简单接收逻辑 char buffer[1024]; int recv_len = recv(socket_of_client, buffer, sizeof(buffer)-1, 0); if (recv_len > 0) { buffer[recv_len] = '\0'; printf("Received from client: %s\n", buffer); } closesocket(socket_of_client); closesocket(socket_of_server); WSACleanup(); return 0; }
编译运行后,你可以用telnet 127.0.0.1 10000或者其他Socket客户端工具连接,就能看到程序进入等待状态并处理连接了。
内容的提问来源于stack exchange,提问作者allentando




