You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因

  1. 字符串缺少终止符:C语言中字符串必须以\0(空字符)作为结束标记。客户端的server_reply和服务器的client_message都是栈上的字符数组,每次接收数据时仅覆盖部分字节,未清空的残留字节会被strlen或puts当作字符串的一部分读取。
  2. 未处理实际收发字节数:服务器未保存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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 16:10:28