C语言Socket服务端仅能接受一次连接问题求助
C语言Socket客户端重复连接失败问题
问题场景
我正在学习C语言Socket编程,编写了基础的客户端和服务端程序。首次编译运行时,客户端能正常收到服务端返回的信息:
The server sent the data: You have reached the server
但再次运行客户端时,会出现如下提示:
Connection FailedThe server sent the data:
即使终止服务端程序、重新编译并运行,问题依然存在。
客户端代码
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> // 包含Socket相关类型定义 #include <sys/socket.h> // 包含Socket API #include <netinet/in.h> // 用于存储地址信息 int main() { int network_socket; // Socket用整数值表示,后续通过该值操作Socket network_socket = socket(AF_INET, SOCK_STREAM, 0); // 创建Socket,指定域、类型和协议 struct sockaddr_in server_address; // 创建服务端地址结构 server_address.sin_family = AF_INET; // 指定Socket类型为互联网域 server_address.sin_port = htons(9002); // 指定端口号 server_address.sin_addr.s_addr = INADDR_ANY; // 指定服务端地址 // 发起连接请求 int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address)); if(connection_status == -1) { printf("Connetion Failed"); } char server_response[256]; recv(network_socket, &server_response, sizeof(server_response), 0); printf("The server sent the data: %s", server_response); return 0; }
服务端代码
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> int main() { char server_message[256] = "You have reached the server\n"; int server_socket; server_socket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(9002); server_address.sin_addr.s_addr = INADDR_ANY; bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address)); listen(server_socket, 5); // 5表示等待连接的最大队列长度 int client_socket; client_socket = accept(server_socket, NULL, NULL); send(client_socket, server_message, sizeof(server_message), 0); return 0; }
问题原因
- 服务端仅处理一次连接就终止:当前服务端在接受一个客户端连接、发送数据后直接退出进程,后续客户端发起连接时没有服务端监听端口,导致连接失败。
- TIME_WAIT状态占用端口:首次连接断开后,TCP连接会进入
TIME_WAIT状态(默认持续2个MSL时长),此时服务端重启绑定同一端口会失败,因为端口被处于TIME_WAIT状态的连接占用。 - 客户端错误处理缺失:连接失败后仍执行
recv操作,此时network_socket是无效句柄,recv返回错误但程序继续打印空内容,导致输出混乱。
修复方案
1. 修改服务端,支持循环处理连接并复用端口
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> // 引入close函数头文件 int main() { char server_message[256] = "You have reached the server\n"; int server_socket = socket(AF_INET, SOCK_STREAM, 0); if(server_socket == -1) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 设置端口复用,避免TIME_WAIT状态占用端口导致绑定失败 int opt = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(9002); server_address.sin_addr.s_addr = INADDR_ANY; if(bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address)) == -1) { perror("bind failed"); close(server_socket); exit(EXIT_FAILURE); } listen(server_socket, 5); printf("Server listening on port 9002...\n"); // 循环接受客户端连接 while(1) { int client_socket = accept(server_socket, NULL, NULL); if(client_socket == -1) { perror("accept failed"); continue; } send(client_socket, server_message, sizeof(server_message), 0); close(client_socket); // 处理完连接后关闭客户端套接字 } close(server_socket); return 0; }
2. 完善客户端错误处理逻辑
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { int network_socket = socket(AF_INET, SOCK_STREAM, 0); if(network_socket == -1) { perror("socket creation failed"); exit(EXIT_FAILURE); } struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(9002); server_address.sin_addr.s_addr = INADDR_ANY; int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address)); if(connection_status == -1) { perror("Connection Failed"); close(network_socket); exit(EXIT_FAILURE); } char server_response[256]; // 预留一个字节存储字符串终止符,避免乱码 ssize_t recv_len = recv(network_socket, server_response, sizeof(server_response)-1, 0); if(recv_len > 0) { server_response[recv_len] = '\0'; // 确保字符串以'\0'结尾 printf("The server sent the data: %s", server_response); } else if(recv_len == 0) { printf("Server closed the connection\n"); } else { perror("recv failed"); } close(network_socket); return 0; }
关键修复说明
- 添加
SO_REUSEADDR选项:通过setsockopt设置该选项,允许服务端在TIME_WAIT状态下重新绑定端口,解决重启服务端后无法绑定的问题。 - 服务端循环处理连接:使用
while(1)持续监听并接受客户端连接,处理完单个连接后关闭客户端套接字,继续等待下一个连接。 - 客户端错误处理优化:连接失败时直接退出程序,避免后续无效操作;
recv后手动添加字符串终止符,防止打印乱码;所有操作完成后关闭套接字。
内容的提问来源于stack exchange,提问作者Cyborg
相关产品推荐
相关产品推荐

