侦听 TCP 端口 0 会为我在系统上分配一个空闲端口号。
但是当我尝试时会发生什么连接到 TCP 端口 0?显而易见的答案是:“这不起作用”:
$ nc localhost 0
nc: port number too small: 0
这是在系统的哪里处理的?在操作系统内核的 TCP 堆栈中? Unix 上是否可以连接到 TCP 端口 0?
答案1
为了确保我们的观点一致(您的问题这样就很含糊),要求在端口 0 上绑定 TCP 表示请求动态生成未使用的端口号。换句话说,在该请求之后您实际监听的端口号不是零。在 上有一条关于此的[linux kernel source]/net/ipv4/inet_connection_sock.c
评论inet_csk_get_port()
:
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
*/
这是标准的 Unix 约定。可能有些系统实际上允许使用端口 0,但这被认为是一种不好的做法。然而,POSIX、IANA 或 TCP 协议并未正式指定此行为。1 你可能会发现这个有趣的。
这就是为什么您无法明智地与端口 0 建立 TCP 连接。大概nc
已经意识到这一点并通知您您提出了一个无意义的请求。如果您在本机代码中尝试此操作:
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 0;
inet_aton("127.0.0.1", &addr.sin_addr);
if (connect(fd, (const struct sockaddr*)&addr, sizeof(addr)) == -1) {
fprintf(stderr,"%s", strerror(errno));
}
您会遇到与尝试连接到任何其他不可用端口时相同的错误:ECONNREFUSED
“连接被拒绝”。所以回复:
这是在系统的哪里处理的?在操作系统内核的 TCP 堆栈中?
可能不会;它不需要特殊处理。也就是说,如果您能找到一个允许在端口 0 上绑定和侦听的系统,那么您大概可以连接到它。
1. 但是 IANA做将端口 0 称为“保留”(看这里)。意思是,这个端口不应该在线使用。这使得动态赋值约定没问题(因为它实际上不会被使用)。将其明确规定为目的可能超出 IANA 的范围;从本质上讲,操作系统可以自由地做他们想做的事,包括什么也不做。
答案2
请求端口 0 会触发操作系统搜索并分配下一个可用端口。这避免了您必须对特定端口进行硬编码或必须搜索可用端口。我的 Linux Mint 系统回归
nc: port range not valid
到
nc localhost 0
答案3
nc -l 0
将要求操作系统侦听端口 0。但正如上面所评论的,大多数操作系统都会看到 0 并调用其特定的习惯来为您的应用程序选择正编号端口,因此nc
最终会侦听某个端口,例如 56514。