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

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){

服务端其他优化点

  1. 文件描述符泄漏:父进程在fork后未关闭newSocketFD,每次新连接都会占用一个文件描述符,最终会耗尽系统资源。父进程需在fork后立即关闭该fd:
if (fork() == 0){
    // 子进程处理连接逻辑
    ...
} else {
    // 父进程关闭不需要的套接字fd
    close(newSocketFD);
}
  1. strlen(buffer)-1的潜在错误:若客户端发送的字符串刚好填满缓冲区(无换行符),strlen(buffer)-1会错误减少长度。需先判断缓冲区末尾是否有换行,再决定是否减1(如前面修复方法中的代码)。

  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:43:09