我有以下 TCP 服务器:
socat TCP-LISTEN:10000,fork,reuseaddr SYSTEM:'read -r msg && sleep 3 && echo "OK"'
当我执行(交互模式)时:
socat - TCP:localhost:10000
> some text here [ENTER]
3 秒后它将返回“OK”(正如预期的那样)
但是,我需要以非交互式的方式进行:
response=$(echo "some text" | socat - TCP:localhost:10000)
但它立即返回而没有响应,并且服务器在 3 秒后报告echo: I/O error
(因为客户端不再连接)。
如果我从服务器上删除“sleep 3”,它可以正常工作,但我需要“sleep”才能工作(因为我实际上正在执行一个可能处于睡眠状态的命令,直到它从另一个服务器收到一些响应)。
如何修复?
- 使用 Ubuntu 22.04
- 它不需要
socat
作为客户端使用 - 最终服务器和客户端将位于不同的服务器上。
答案1
Socat 适用于半关闭套接字。这意味着,当它在一个地址(在您的情况下为 TCP 连接)上收到 EOF(关闭)时,它会关闭第二个地址的写入通道,默认情况下只给它 0.5 秒的时间,直到它完全关闭连接。
因此,即使在交互模式下,如果您在 3 秒内按下 ^D,也会出现 I/O 错误。
可能的解决方案包括:
推迟客户端的 EOF:
response=$( { echo "some text"; sleep 4; } | socat - TCP:localhost:10000)
或者增加两个进程的半关闭超时时间:
socat -t 3.1 TCP-LISTEN:10000,fork,reuseaddr SYSTEM:'read -r msg && sleep 3 && echo "OK"'
response=$(echo "some text" | socat -t 3.1 - TCP:localhost:10000)
答案2
使用nc
效果符合预期:
echo "message" | nc localhost 10000
如果有人可以解释为什么socat
不一样或者如何使它工作socat
,我会接受这个答案。