netcat 如何从两个不同的终端侦听同一主机上的同一端口?

Sim*_*mon 6 sockets tcp netcat

为什么当我从两个不同的终端执行以下命令(在我的 Debian 8.4 机器上)时,它不会输出“地址已使用”类型的错误?

netcat -p 1234 -l
Run Code Online (Sandbox Code Playgroud)

我想知道为什么它不会抛出错误,因为它启动了两个进程侦听同一个端口。
netcat 不使用套接字吗?这怎么可能?

a3n*_*3nm 8

在我的系统上,运行strace nc -l 1234结束于:

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 1)                            = 0
accept(3, 
Run Code Online (Sandbox Code Playgroud)

因此,套接字是使用选项SO_REUSEADDR和来设置的SO_REUSEPORT,它允许多个进程绑定到相同的端口和相同的侦听地址。请参阅man 7 socket这个详细答案。此选项的目标是允许一种简单的负载平衡形式:端口的传入连接将被重定向到其中一个进程(显然是随机的)。


Rem*_*eau 0

-p选项指定源端口,而不是侦听端口

-l选项将 netcat 置于监听模式。

在您的示例中,1234是选项的输入值-p,而不是-l选项,这意味着没有指定显式侦听端口。如果 netcat 没有失败,那么很可能 netcat 绑定到端口 0,这告诉侦听套接字绑定到随机可用的临时端口。因此,您的两个 netcat 实例实际上会侦听不同的端口。使用netstat来验证。

根据netcat 的 Linux 手册页

-l' 用于指定 nc 应侦听传入连接而不是发起与远程主机的连接。将此选项与 -p、-s 或 -z 选项结合使用是错误的。此外,使用 -w 选项指定的任何超时都将被忽略。

-p source_port
指定 nc 应使用的源端口,但受权限限制和可用性的限制。 将此选项与 -l 选项结合使用是错误的。

因此从技术上讲,您的示例可能一开始就无效。

然而,在某些系统上,包括一些 Debian 安装,根据您使用的 netcat 风格(特别是传统风格),您实际上可能需要一起使用-l-p,但您需要交换它们的顺序才能正确指定侦听端口,例如:

nc -l -p 1234
Run Code Online (Sandbox Code Playgroud)

  • 但可以多次监听同一端口:`nc -l 1234` https://imgur.com/a/u1xSyjU 为什么? (5认同)
  • 抱歉,这不是解释:在两个不同的终端中运行“nc -l 1234”工作正常。 (2认同)