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;
错误原因分析
输出缓冲区未刷新导致视觉卡顿
C语言中printf默认采用行缓冲模式,只有输出内容包含换行符\n时,才会立即将缓冲区内容打印到终端。服务器的printf("Came");和客户端的printf("Yes");都没有换行符,导致输出内容停留在缓冲区,看起来像程序卡住,但实际程序仍在运行。客户端输入缓冲区残留换行符引发阻塞
第一次用scanf("%[^\n]", client_message)读取输入时,用户按下的回车(换行符\n)会残留在输入缓冲区。第二次调用scanf("%[^\n]", client_message)时,%[^\n]会读取到换行符就停止,无法获取有效输入,程序卡在等待输入状态;服务器则卡在第二次recv调用等待客户端消息,形成两端互相等待的死锁。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
相关产品推荐
相关产品推荐

