C套接字问题:服务器回复为何携带客户端历史消息内容?
C套接字服务器回复包含历史内容问题分析与解决
问题描述
开发C套接字程序时遇到异常:服务器回复的消息中总是包含客户端之前发送过的内容。
客户端代码
while(1){ char message[1000], server_reply[2000]; printf("Please enter the message: "); scanf("%s",message); puts(message); if (send(sock,message,strlen(message),0)< 0){ printf("ERROR writing to socket"); return 1; } if (recv(sock,server_reply,2000,0)<0){ puts("recv failed"); break; } puts("server reply"); puts(server_reply); } close(sock); return 0; }
服务器代码
while(1){ char client_message[1000]; recv(client_socket, client_message, 2000,0); puts(client_message); write(client_socket,client_message, strlen(client_message)); } if(read_size==0){ puts("client disconnected"); fflush(stdout); } else if(read_size==-1){ perror("recv failed"); } return 0; }
复现示例
- 输入消息:Elephant,服务器回复:Elephant
- 输入消息:Jake,服务器回复:Jakehant
- 输入消息:Two,服务器回复:Twophant
问题原因
- 字符串缺少终止符:C语言中字符串必须以
\0(空字符)作为结束标记。客户端的server_reply和服务器的client_message都是栈上的字符数组,每次接收数据时仅覆盖部分字节,未清空的残留字节会被strlen或puts当作字符串的一部分读取。 - 未处理实际收发字节数:服务器未保存
recv的返回值(实际接收的字节数),直接用strlen(client_message)计算发送长度,但client_message可能没有正确的终止符,导致strlen计算错误;客户端recv后也未手动添加终止符,无法截断残留内容。
解决方法
客户端修改
核心是在recv后手动添加终止符,并处理recv的返回值:
while(1){ char message[1000], server_reply[2000]; printf("Please enter the message: "); scanf("%s",message); puts(message); if (send(sock, message, strlen(message), 0) < 0){ printf("ERROR writing to socket"); return 1; } ssize_t recv_len = recv(sock, server_reply, sizeof(server_reply)-1, 0); if (recv_len < 0){ puts("recv failed"); break; } else if (recv_len == 0) { puts("server disconnected"); break; } // 添加终止符,确保字符串正确结束 server_reply[recv_len] = '\0'; puts("server reply"); puts(server_reply); } close(sock); return 0; }
服务器修改
核心是初始化缓冲区、保存recv返回值、用实际接收长度发送:
ssize_t read_size; while(1){ // 初始化缓冲区,清空所有字节 char client_message[1000] = {0}; read_size = recv(client_socket, client_message, sizeof(client_message)-1, 0); if (read_size <= 0) { break; } // 添加终止符,保证puts正确输出 client_message[read_size] = '\0'; puts(client_message); // 使用实际接收的字节数发送,避免依赖strlen的错误计算 write(client_socket, client_message, read_size); } if(read_size == 0){ puts("client disconnected"); fflush(stdout); } else if(read_size == -1){ perror("recv failed"); } return 0; }
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

