使用命名管道作为 netcat 的数据源

使用命名管道作为 netcat 的数据源

我想使用 netcat 作为从命名管道读取数据的 TCP 服务器。为此,我做了以下操作:

步骤 1. 创建管道和使用它作为源的服务器

mkfifo /tmp/all.pipe
nc -k -l 8080 < /tmp/all.pipe

步骤2.创建一个连续读取数据的客户端:

while true; do
    sleep 1;
    echo "Check connection";
    while IFS= read -r line; do
        printf "$line";
    done < /dev/tcp/localhost/8080;
done

步骤 3. 将一些数据写入管道:

echo "hello" > /tmp/all.pipe

执行这 3 个步骤后,客户端的输出为:

...
bash: connect: Connection refused
bash: /dev/tcp/localhost/8080: Connection refused
Check connection
bash: connect: Connection refused
bash: /dev/tcp/localhost/8080: Connection refused
Check connection
hello

然而,当我再次执行步骤 3 时,输出没有改变。看起来发生这种情况是因为连接仍然处于活动状态,但新数据没有从管道传递到 nc,然后传递到客户端。为什么?可以做什么来实现它?

答案1

之上:

nc -k -l 8080 < /tmp/all.pipe

shell 尝试打开/tmp/all.pipe但挂起,因为还没有进程打开命名管道进行写入。

既然nc还没有开始,这就解释了为什么bash会得到一个连接被拒绝当尝试在那里连接时。

当你这样做时

echo "hello" > /tmp/all.pipe

然后第一个命令就被解锁了。现在管道已被实例化。

然后在那里echo写入hello\n并终止,此时管道的写入端关闭,并且nc将在其标准输入上看到文件结尾。如果您使用,cat代替nc,cat就会终止。

但是对于nc,它的标准输出仍然会在这一点上到达终端,并且 TCP 连接仍然处于活动状态,因此即使有一端已到达输入结束,它也会继续。例如,如果bash在该套接字上发送某些内容,则会显示在 的 stdout 上。nc

当您执行第二个操作时echo something > /tmp/all.pipe,因为nc尚未关闭管道上的 fd(至少是Ubuntu 上的nc软件包中的情况netcat-openbsd,YMMV),它确实会通过再次上线的同一个管道,但nc已经放弃了读取从那以后,它已经到达了 eof 较早。

这里最简单的可能是以读+写模式打开 's 输入的管道,nc这样它就会立即实例化,并且总是与nc生命一样长。

为此,只需在命令行上替换<为:<>nc

nc -k -l 8080 <> /tmp/all.pipe

另请注意,第一个参数printf是格式,那里不应该有任何变量。如果要打印不带行分隔符的输入行,请使用:

printf %s "$line"

相关内容