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

使用Socat运行程序作为服务器时响应顺序错乱且延迟输出问题

问题原因与解决方案:Socat运行C程序服务器时的输出异常

问题描述

你尝试用Socat将一个简单的C程序作为TCP服务器运行,但遇到两个异常:

  1. 服务器的响应顺序不正确;
  2. 客户端只有发送完所有数据后,才能收到服务器的响应。

原C程序代码

#include <stdio.h>
int main(int argc, char *argv[]){
    char buff[64];
    char t[10];
    printf("Welcome\n");
    gets(t);
    printf(t);
    printf("\n");
    gets(buff);
    return 0;
}

Socat运行时的异常现象

  • 服务器端执行命令及输出:
$ socat -v tcp-listen:4444,reuseaddr,fork exec:"./test"
> 2018/05/24 10:33:42.102445 length=2 from=0 to=1 a
> 2018/05/24 10:33:42.582042 length=2 from=2 to=3 a
< 2018/05/24 10:33:42.583721 length=10 from=0 to=9 Welcome a
$ socat -v tcp-listen:4444,reuseaddr,fork exec:"./leak"
> 2018/05/24 10:39:02.551405 length=7 from=0 to=6 FOOBAR
> 2018/05/24 10:39:03.511667 length=5 from=7 to=11 LALA
< 2018/05/24 10:39:03.512021 length=15 from=0 to=14 Welcome FOOBAR
  • 客户端执行命令及输出:
$ nc 192.168.2.230 4444
FOOBAR
LALA
Welcome
FOOBAR

而直接运行程序时一切正常:

$ ./test
Welcome
FOOBAR
FOOBAR
:)

问题根源

核心原因是标准输出(stdout)的缓冲机制随输出目标不同而变化:

  • 当程序直接在终端运行时,stdout默认是行缓冲模式——只要输出中包含换行符\n,就会立即将缓冲内容刷新到终端,所以printf("Welcome\n")会马上显示出来。
  • 当通过Socat的exec选项启动程序时,stdout被关联到管道而非终端,此时stdout会自动切换为全缓冲模式。程序输出的内容会先暂存在内存缓冲中,只有当缓冲被填满、程序退出,或者主动调用刷新函数时,才会一次性将缓冲内容发送给客户端。

这就导致了:

  • 服务器的"Welcome"提示被缓冲,直到客户端发送完所有数据、程序执行后续输出操作后,才和其他内容一起被发送;
  • 客户端无法实时收到服务器的响应,必须等自己发送完所有数据才能看到结果。

解决方案:关闭标准输出缓冲

在程序的开头添加setbuf(stdout, 0);语句,强制关闭stdout的缓冲,让所有输出内容立即被发送到客户端。

修改后的完整代码

#include <stdio.h>
int main(int argc, char *argv[]){
    setbuf(stdout, 0);
    char buff[64];
    char t[10];
    printf("Welcome\n");
    gets(t);
    printf(t);
    printf("\n");
    gets(buff);
    return 0;
}

修改后重新通过Socat启动服务器,客户端会立即收到"Welcome"提示,输出顺序也会和直接运行程序时完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:08:43