C语言TCP套接字客户端阻塞求助:fgets接收服务器返回数据卡住
问题分析与修复方案
核心阻塞原因:缺少换行符导致fgets等待
客户端的fgets会一直阻塞,直到读取到**换行符\n**或连接关闭(触发EOF)。服务端生成长度字符串后,仅用fputs发送纯数字,末尾没有换行符,客户端的fgets会一直等待换行,直到服务端退出(连接关闭)才会返回数据。
修复方法:服务端发送长度时,在字符串末尾添加换行符,可直接用fprintf简化操作:
// 替换原有的sprintf和fputs size_t len = strlen(buffer); if (len > 0 && buffer[len-1] == '\n') { len--; // 去掉fgets读取的换行符 } fprintf(fp, "%zu\n", len); fflush(fp);
客户端输入截断问题
客户端代码中fgets(buffer, sizeof(buffer), stdin)存在错误:buffer是指针,sizeof(buffer)返回的是指针本身的大小(如64位系统为8字节),而非你malloc的1024字节,这会导致输入长字符串被截断。
修复方法:直接使用定义好的缓冲区大小,或用宏统一管理:
#define BUFFER_SIZE 1024 char *buffer = malloc(sizeof(char)*BUFFER_SIZE); // 读取输入时传入正确的长度 if(fgets(buffer, BUFFER_SIZE, stdin) == NULL){
服务端其他优化点
- 文件描述符泄漏:父进程在
fork后未关闭newSocketFD,每次新连接都会占用一个文件描述符,最终会耗尽系统资源。父进程需在fork后立即关闭该fd:
if (fork() == 0){ // 子进程处理连接逻辑 ... } else { // 父进程关闭不需要的套接字fd close(newSocketFD); }
strlen(buffer)-1的潜在错误:若客户端发送的字符串刚好填满缓冲区(无换行符),strlen(buffer)-1会错误减少长度。需先判断缓冲区末尾是否有换行,再决定是否减1(如前面修复方法中的代码)。stdio缓冲的替代方案:用
fdopen将套接字转为FILE*虽然方便,但stdio缓冲可能带来意外问题。若想更直接控制套接字读写,可改用底层的read/write函数,避免依赖fflush强制刷新缓冲。
修复后的代码片段示例
服务端子进程处理代码
if (fork() == 0){ FILE *fp; if ((fp = fdopen(newSocketFD, "r+")) == NULL){ perror("error opening file"); close(newSocketFD); exit(1); } #define BUFFER_SIZE 1024 char *buffer = malloc(sizeof(char)*BUFFER_SIZE); if (!buffer) { perror("malloc failed"); fclose(fp); close(newSocketFD); exit(1); } while(fgets(buffer, BUFFER_SIZE, fp) != NULL){ printf("server: string gotten - %s", buffer); size_t len = strlen(buffer); if (len > 0 && buffer[len-1] == '\n') { len--; } fprintf(fp, "%zu\n", len); fflush(fp); } free(buffer); fclose(fp); close(newSocketFD); exit(0); } else { close(newSocketFD); }
客户端主循环代码
#define BUFFER_SIZE 1024 char *buffer = malloc(sizeof(char)*BUFFER_SIZE); if (!buffer) { perror("malloc failed"); exit(1); } for (;;){ printf("Please enter a string:\n"); if(fgets(buffer, BUFFER_SIZE, stdin) == NULL){ perror("reading string from stdin failed"); continue; } if(fputs(buffer, fp) == EOF){ perror("fput command failed"); continue; } fflush(fp); if(fgets(buffer, BUFFER_SIZE, fp) == NULL){ perror("error getting length of string. server not working."); fclose(fp); close(socketFD); free(buffer); exit(1); } printf("The size of the string that was typed is: %zu\n", atoi(buffer)); fflush(stdout); }
内容的提问来源于stack exchange,提问作者ahmed33033
相关产品推荐
相关产品推荐

