我正在尝试编写一个请求/响应 TCP 服务器来处理少量非常简单的命令。我使用 shell 脚本是为了尽可能便于移植,避免编译或需要编程语言的特定运行时。
我希望它能够响应客户端说出命令的结果,这意味着响应必须是动态的。
我目前正在尝试使用nc
:
mkfifo commands
mkfifo nc_responses
nc -k -l 47201 >commands < <(tail -f nc_responses) &
while read -r command; do
echo "Got $command"
echo "Ran $command" >nc_responses
done <commands
这是在第二个 shell 中调用它的输出:
$ nc localhost 47201 <<< 'command 1'
$ nc localhost 47201 <<< 'command 2'
Ran command 1
$ nc localhost 47201 <<< 'command 3'
Ran command 2
$ nc localhost 47201 <<< 'command 4'
Ran command 3
正如您所看到的,响应滞后于请求一。
任何人都可以找到解决此问题的方法,以便从请求动态生成响应吗?
(对于上下文 - 这是使用bash
on macOS
, withmacOS
的内置nc
)
答案1
在其他地方重复这个建议: https://superuser.com/a/998731
看起来问题出在客户端而不是服务器上;
nc localhost 47201 <<< 'command 1'`
没有保持连接打开足够长的时间以使响应通过。
这有效:
{ echo 'command 1'; sleep 0.1; } | nc localhost 47201
虽然使用睡眠感觉很糟糕!我想知道客户端是否有更好的方法来等待(超时?)已知终端的响应?
EOF 不容易工作,因为我无法为每个连接打开一个新的输入管道。
答案2
虽然它可能与问题无关,但这是使用以下方法实现类似功能的另一种方法索卡特代替网猫。无需使用命名管道或睡眠。有关更多信息,请参阅 socat 手册。
服务器:
> socat TCP-LISTEN:5000,reuseaddr,fork SYSTEM:'read -r command \
echo "Run $command from $SOCAT_PEERADDR" >&2 \
$command'
Run date from 127.0.0.1
客户:
> socat - TCP:localhost:5000 <<<"date"
Wed Dec 22 03:37:02 PM CST 2021
无论如何,打开允许任意连接执行不受约束的命令的端口从来都不是一个好主意。