【发布时间】:2015-06-26 00:19:38
【问题描述】:
如何使用nc 创建一个 TCP 连接来监听多个主机?
nc -l -p 12345
【问题讨论】:
-
您可能想澄清您是要创建多个 TCP 连接 到
nc(例如来自一堆其他客户端)还是要收听 on 多个 TCP/IP 地址而不是监听一个并使标题和文本兼容 -
@HansZ。多个tcp连接,让多个客户端连接到一个socket。
如何使用nc 创建一个 TCP 连接来监听多个主机?
nc -l -p 12345
【问题讨论】:
nc(例如来自一堆其他客户端)还是要收听 on 多个 TCP/IP 地址而不是监听一个并使标题和文本兼容
netcat 无法同时连接。您应该使用类似ucspi-tcp 的tcpserver 工具或利用xinetd,因为您使用的是Linux。
见:https://superuser.com/questions/232747/netcat-as-a-multithread-server
可以通过在完成后重新启动netcat 的 shell 脚本来处理连续连接。
【讨论】:
ncat可以做到。
例如ncat --broker --listen -p 12345 会将所有传入消息分发给所有其他客户端(将其视为集线器)。
【讨论】:
ncat -l -p 12345 做了 OP 想要的。使用--broker 的示例很有趣,但与这个特定问题无关。
ncat -k -l -p 12345吗?没错,我在上面发布的命令行不起作用,但是--broker 会导致监听进程不向标准输出输出任何内容,而是将它收到的所有数据复制回(其他)客户端,这绝对不是什么OP要求。
我推荐socat 作为nc 的替代品。
对于 OP 的问题,socat - TCP-LISTEN:12345,fork,reuseaddr 可以解决。
【讨论】:
-k
强制 nc 在其当前连接完成后继续侦听另一个连接。在没有 -l 选项的情况下使用该选项是错误的。
【讨论】:
使用nc 无法打开到同一个端口的并行连接,但是您可以欺骗nc 打开到同一个端口的多个连接。
为了理解这一点,假设您开始使用$ nc -l -p 4444 -v 监听4444 端口。现在,如果你检查$ netstat -anp | grep 4444 的输出,你会得到它的状态为 LISTEN,在这里它的 pid 是 3410。
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3410/nc
现在,在它连接到客户端后,假设您运行$ nc localhost 4444 -v,它的状态将变为 ESTABLISHED。现在,尝试运行$ netstat -anp | grep 4444,您将看到它的状态为 ESTABLISHED,查看相同的 pid 3410,以及一个 pid 为 3435 的客户端进程
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
请注意,没有可用的侦听端口,因此您不能拥有另一个客户端进程。但是,如果您再次运行$ nc -l -p 4444 -v,您可以有一个监听端口并且可以有多个客户端进程。
在您开始侦听同一端口后查看netstat -anp | grep 4444 输出。
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3476/nc
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
将新客户端附加到同一端口后,请参阅netstat -anp | grep 4444 输出。
tcp 0 0 127.0.0.1:4444 127.0.0.1:46694 ESTABLISHED 3476/nc
tcp 0 0 127.0.0.1:46678 127.0.0.1:4444 ESTABLISHED 3435/nc
tcp 0 0 127.0.0.1:4444 127.0.0.1:46678 ESTABLISHED 3410/nc
tcp 0 0 127.0.0.1:46694 127.0.0.1:4444 ESTABLISHED 3483/nc
你可以说连接行为是这样的:
SERVER_PROCESS_1 <---> CLIENT_PROCESS_1
SERVER_PROCESS_2 <---> CLIENT_PROCESS_2
所以,你可以编写一些脚本来模拟这种行为,或者使用这个 bash 脚本来修改。
#!/usr/bin/bash
lport="4444"
i=0;
while [ true ]; do
echo "opening socket $(( i++ ))";
if [[ "$(ss sport = :$lport -l -H | wc -l)" -eq 0 ]]; then
nc -l -vv -p $lport &
#do something else to process or attach different command to each diff server process
fi;
if [[ "$(ss sport = :$lport -l -H | wc -l)" -ne 0 ]]; then
watch -n 0.1 -g "ss sport = :$lport -l -H" > /dev/null;
fi;
if [[ i -eq 10 ]]; then
break;
fi;
done;
在此处每次客户端使用连接时,此脚本都会启动新的侦听套接字。
但是,可以在 ncat 中更改此行为(此处使用 -k),您可以通过以下示例进行分析:
服务器使用$ ncat -l -p 4444 -v -4 -k 启动,3 个客户端使用$ ncat -4 localhost 4444 启动。现在$ netstat -anp | grep 4444 的输出是:
tcp 0 0 0.0.0.0:4444 0.0.0.0:* LISTEN 3596/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46726 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:46726 127.0.0.1:4444 ESTABLISHED 3602/ncat
tcp 0 0 127.0.0.1:46722 127.0.0.1:4444 ESTABLISHED 3597/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46724 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:4444 127.0.0.1:46722 ESTABLISHED 3596/ncat
tcp 0 0 127.0.0.1:46724 127.0.0.1:4444 ESTABLISHED 3601/ncat
每次新客户端连接时,服务器都会派生其进程以附加到客户端,因此每个服务器进程都使用相同的 pid。因此,服务器的输出以这种方式共享给每个连接的客户端,但是每个客户端都可以向服务器发送单独的消息。
你可以说连接行为是这样的:
SERVER_PROCESS_1 <---> CLIENT_PROCESS_1
SERVER_PROCESS_1 <---> CLIENT_PROCESS_2
SERVER_PROCESS_1 <---> CLIENT_PROCESS_3
没有-k,ncat 的行为将与nc 相同。
可以根据需要如何定义收益或损失。
对于这个例子,我使用了nc 或nc.traditional (v1.10-41.1+b1) 和ncat (7.80)。
【讨论】:
这是一个不完整的答案,因为我没有让它工作。事实上,可以说更多的是一个问题。也许其他人可以完成它。
首先,netcat 似乎有不同的版本。我在 Ubuntu 上,所以我可能已经获得了 Ubuntu 附带的版本。当我nc -h 时,它说:
OpenBSD netcat (Debian patchlevel 1.187-1ubuntu0.1)
当我运行man nc 时,它会这样说:
-F Pass the first connected socket using sendmsg(2) to stdout and exit. This
is useful in conjunction with -X to have nc perform connection setup with
a proxy but then leave the rest of the connection to another program (e.g.
ssh(1) using the ssh_config(5) ProxyUseFdpass option).
在我看来,这意味着它不是使用标准输入和标准输出做通常的事情,而是将一些东西打印到标准输出。然后,另一个进程可以使用该东西来与客户端进行实际连接。
不幸的是,-F 没有我能看到的效果。所以也许我做错了。或者也许有一些我必须听的秘密管道,或者他们忘记记录的补充论点。或者,也许我碰巧有一个损坏的 netcat 构建,它适用于所有使用 Ubuntu 的人。
结合-k 选项(或者,如果失败,则使用while-true 循环),这将允许许多不同的客户端拥有单独的连接。假设您有一个名为handle_connection 的可执行文件,它将来自客户端的输入文件描述符和客户端的输出文件描述符作为参数,并生成一个与客户端通信的子进程。那么服务器脚本可能如下所示:
nc -lkF $host $port | while read in out ; do
handle_connection $in $out ;
done
【讨论】:
ncat 可以,但是用 ncat 的正确命令是:
ncat --keep-open --listen -p 12345
这将同时接受多个连接。
然后您可以使用多个客户端发送数据。例如在两个或更多终端中打开,然后尝试在那里输入:
nc localhost 12345
【讨论】: