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

C语言TCP Socket通信:客户端两次发消息程序卡顿问题排查

TCP客户端与服务器两次交互卡顿问题排查

问题描述

我用C语言编写了TCP服务器与客户端程序,二者建立TCP连接后可正常交换消息,但当期望客户端向服务器发送两次消息时,第二次交互阶段两端程序均出现卡顿现象。以下是相关代码,请帮忙排查错误以实现正常的两次消息交互。

服务器代码(Server.c)

// Connection already established upto this point

// ------------------------------------- First Time -------------------------------
printf("Receving messages ...\n");

if (recv(client_sock, client_message, sizeof(client_message), 0) < 0)
{
        printf("Receive Failed. Error!!!!!");
        return -1;
}

printf("Client Message: %s\n", client_message);

strcpy(server_message, client_message);

// successfully send the message to the client but does not proceed after this line , where client_sock is the socket of client returned by 'accept' funtion call
if (send(client_sock, server_message, strlen(server_message), 0) < 0)
{
        printf("Send Failed. Error!!!!!");
        return -1;
}

printf("Came"); //Stuck here i.e this print statement doesn't get executed

// ------------------------------------- Second Time -------------------------------
printf("Receving messages ...");
memset(client_message, '\0', sizeof(client_message));

if (recv(client_sock, client_message, sizeof(client_message), 0) < 0)
{
        printf("Receive Failed. Error!!!!!");
        return -1;
}

printf("Client Message: %s\n", client_message);

strcpy(server_message, client_message);

if (send(client_sock, server_message, strlen(server_message), 0) < 0)
{
        printf("Send Failed. Error!!!!!");
        return -1;
}

close(client_sock);
close(socket_desc);
return 0;

客户端代码

printf("Connected\n");
// ------------------------------------- First Time -------------------------------
// Get Input from the User
printf("Enter Message: ");
scanf("%[^\n]", client_message);

if (send(socket_desc, client_message, strlen(client_message), 0) < 0) {
        printf("Send Failed. Error!!!!");
        return -1;
}

if (recv(socket_desc, server_message, sizeof(server_message), 0) < 0) {
        printf("Receive Failed. Error!!!!!");
        return -1;
}

printf("Server Message: %s\n", server_message);

printf("Yes"); // stuck here , this statement doesn't get executed
memset(server_message, '\0', sizeof(server_message));
memset(client_message, '\0', sizeof(client_message));

// ------------------------------------- Second Time -------------------------------
printf("Enter Message: ");
scanf("%[^\n]", client_message);

if (send(socket_desc, client_message, strlen(client_message), 0) < 0) {
        printf("Send Failed. Error!!!!");
        return -1;
}

if (recv(socket_desc, server_message, sizeof(server_message), 0) < 0) {
        printf("Receive Failed. Error!!!!!");
        return -1;
}

printf("Server Message: %s\n", server_message);

memset(server_message, '\0', sizeof(server_message));
memset(client_message, '\0', sizeof(client_message));

// Closing the Socket
// close(socket_desc);

return 0;

错误原因分析

  1. 输出缓冲区未刷新导致视觉卡顿
    C语言中printf默认采用行缓冲模式,只有输出内容包含换行符\n时,才会立即将缓冲区内容打印到终端。服务器的printf("Came");和客户端的printf("Yes");都没有换行符,导致输出内容停留在缓冲区,看起来像程序卡住,但实际程序仍在运行。

  2. 客户端输入缓冲区残留换行符引发阻塞
    第一次用scanf("%[^\n]", client_message)读取输入时,用户按下的回车(换行符\n)会残留在输入缓冲区。第二次调用scanf("%[^\n]", client_message)时,%[^\n]会读取到换行符就停止,无法获取有效输入,程序卡在等待输入状态;服务器则卡在第二次recv调用等待客户端消息,形成两端互相等待的死锁。

  3. TCP接收数据未添加字符串结束符
    recv不会自动为接收的数据添加\0结束符,直接用printf("%s")或strlen()处理时,可能访问到内存垃圾数据,引发未定义行为。

修复方案

1. 刷新输出缓冲区

给无换行的printf添加换行符,或手动调用fflush(stdout)强制刷新:

  • 服务器端:改为printf("Came\n"); 或执行printf("Came"); fflush(stdout);
  • 客户端:改为printf("Yes\n"); 或执行printf("Yes"); fflush(stdout);

2. 处理输入缓冲区残留换行符

两种解决方式任选其一:

  • 方式一:第一次scanf后调用getchar()读取残留换行符:
    scanf("%[^\n]", client_message);
    getchar(); // 清除输入缓冲区的换行符
    
  • 方式二:在scanf格式串前加空格,跳过所有空白字符(包括换行):
    scanf(" %[^\n]", client_message); // 注意格式串前的空格
    

3. 为TCP接收数据添加结束符

接收数据时记录返回长度,手动添加\0:

  • 服务器端接收逻辑修改:
    int recv_len = recv(client_sock, client_message, sizeof(client_message)-1, 0);
    if (recv_len < 0)
    {
            printf("Receive Failed. Error!!!!!");
            return -1;
    }
    client_message[recv_len] = '\0'; // 添加字符串结束符
    
  • 客户端接收逻辑同理修改:
    int recv_len = recv(socket_desc, server_message, sizeof(server_message)-1, 0);
    if (recv_len < 0) {
            printf("Receive Failed. Error!!!!!");
            return -1;
    }
    server_message[recv_len] = '\0';
    

内容的提问来源于stack exchange,提问作者Huzaifa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:01:37