使用C Sockets实现客户端/服务端遇errno=101(网络不可达)问题求助
客户端连接服务端失败:errno=101(Network is unreachable)排查方案
我正在用C Socket实现简单的客户端/服务端程序,但客户端无法连接到服务端,报错errno=101: Network is unreachable。我已通过SSH接入私有网络,客户端和服务端在同一局域网,使用192.168.x.x段IP,按道理应该没问题,求解决思路。
相关代码
int main(int argc, char* argv[]) { if (argc == 1) { int sockfd, connfd; struct sockaddr_in servaddress, cliaddress; socklen_t servaddr_size; int n; printf("Welcome to Chat!\n"); //create socket sockfd = socket(AF_INET, SOCK_STREAM, 0); // IPv4, TCP, IP if (sockfd == -1) { printf("Socket creation failed...\n"); exit(0); } else { memset(&servaddress, '\0', sizeof(servaddress)); servaddress.sin_family = AF_INET; servaddress.sin_port = htonl(0); servaddress.sin_addr.s_addr = htonl(INADDR_ANY); n = bind(sockfd, (struct sockaddr*)&servaddress, sizeof(servaddress)); if (n < 0) { printf("Socket bind failed...\n"); exit(0); } socklen_t servsize = sizeof(servaddress); getsockname(sockfd, (struct sockaddr*) &servaddress, &servsize); printf("Waiting for a connection on %s ", inet_ntoa(servaddress.sin_addr)); printf("port %d\n", ntohs(servaddress.sin_port)); if ((listen(sockfd, 5)) != 0) { printf("Listen failed...\n"); exit(0); } else { printf("Server listening..\n"); } while(1) { servaddr_size = sizeof(cliaddress); connfd = accept(sockfd, (struct sockaddr*)&cliaddress, &servaddr_size); if(connfd < 0) { printf("can't accept connection...\n"); exit(0); } else { printf("Found a friend! You receive first.\n"); servcomm(connfd); close(sockfd); } } } } else if(argc == 2) { printf("Invalid number of arguments.\n"); exit(1); } else if(argc > 2) { int sockfd; struct sockaddr_in servaddress; char* portval; char* ipval; for(int i = 0; i < argc; i++) { if(strcmp(argv[i], "-s") == 0) { ipval = argv[i+1]; while(*ipval) { if((isdigit(*ipval) == 0) && (*ipval != '.')) { printf("IP is not valid.\n"); exit(0); } ipval++; } } if(strcmp(argv[i], "-p") == 0) { portval = argv[i+1]; while(*portval) { if(isdigit(*portval++) == 0) { printf("Port is not valid.\n"); exit(0); } } } } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("Socket creation failed...\n"); exit(0); } memset(&servaddress, '\0', sizeof(servaddress)); servaddress.sin_family = AF_INET; servaddress.sin_port = htonl(atoi(portval)); servaddress.sin_addr.s_addr = inet_addr(ipval); // printf("portval %s\n", portval); // printf("ipval %s\n", ipval); // printf("atoi %d\n", atoi(portval)); // printf("port %d\n", servaddress.sin_port); // printf("ip %d\n", servaddress.sin_addr.s_addr); printf("Connecting to server...\n"); errno = 0; if(connect(sockfd, (struct sockaddr*)&servaddress, sizeof(servaddress)) != 0) { printf("connection to server failed...\n"); printf("Error occurred while connecting, errno=%d, %s\n", errno, strerror(errno)); exit(0); } else { printf("Connected!\n"); printf("Connected to a friend! You send first.\n"); } clicomm(sockfd); close(sockfd); } return 0; }
排查与修复思路
1. 端口转换函数错误
客户端代码中设置端口用了htonl(atoi(portval)),但servaddress.sin_port是16位字段,正确的转换函数应该是htons()(转换16位整数),htonl()是转换32位整数,会导致端口值被错误扩展,服务器监听的端口和客户端连接的端口不匹配。
2. IP地址指针被篡改
客户端解析-s参数时,直接对ipval做自增遍历检查,导致最后ipval指向的是字符串末尾的空字符,后续调用inet_addr(ipval)传入的是空字符串,会返回INADDR_NONE(对应255.255.255.255广播地址),无法连接到正确服务器IP。
修复方法:保存原始IP指针,遍历用临时变量:
if(strcmp(argv[i], "-s") == 0) { char* original_ip = argv[i+1]; char* temp_ip = original_ip; while(*temp_ip) { if((isdigit(*temp_ip) == 0) && (*temp_ip != '.')) { printf("IP is not valid.\n"); exit(0); } temp_ip++; } ipval = original_ip; }
3. 服务器套接字错误关闭
服务器端accept成功后调用了close(sockfd);,这会关闭监听套接字,导致后续无法接受新连接。正确做法是关闭connfd(连接套接字),保留sockfd继续监听:
servcomm(connfd); close(connfd); // close(sockfd); 移除这行
4. 网络层面验证
- 在服务器机器上执行
ss -tulpn | grep <进程名>,确认服务端确实在监听预期的端口(INADDR_ANY表示监听所有网卡)。 - 在客户端机器上用
ping <服务器IP>测试网络连通性,确保没有路由问题。 - 用
telnet <服务器IP> <端口>手动尝试连接,排除防火墙、SELinux等系统级限制。 - 检查SSH隧道的端口转发配置(如果有),确保没有端口冲突或转发错误。
内容的提问来源于stack exchange,提问作者ash
相关产品推荐
相关产品推荐

