让我用一个例子来更具体地说明我的问题:假设我有很多小型服务器,这些服务器都使用TCPv4在不同的端口上启动。当然,这些端口将成为目标端口。让我们进一步假设这些小型服务器不仅像典型服务器那样在启动时启动,而是根据需求动态地变动。它们会在需要时启动,并且可能会关闭一段时间,然后稍后再次启动。
现在让我们说,在同一台计算机上,我们还有许多客户端进程通过TCPv4向其他计算机上的服务器进程发出请求。当客户端发出这样的请求时,操作系统会为其分配源端口。
就本示例而言,让我们说一个客户端进程向运行在另一台计算机上的RESTful服务器发出Web请求。还要说操作系统分配给该请求的源端口是端口7777。
对于此示例,我们还要说,在上述请求仍在发生的同时,我们的一台小型服务器希望启动,并且希望在目标端口7777上启动。
我的问题是,这会引起冲突吗?即,由于端口7777已被使用,服务器会收到错误消息吗?还是因为这两种端口位于互不冲突的不同地址空间中,一切都会好起来吗?
我担心这里可能发生冲突的一个原因是,我看到网页上说“临时源端口选择”通常是在一个相对较高的端口号范围内进行的。这是一个网页:
https://www.cymru.com/jtk/misc/ephemeralports.html
为什么源端口以高数量开始而不是仅从1开始的自然假设是,避免与服务器进程使用的目标端口冲突。尽管我还没有看到任何明显出现的东西,并说是这种情况。
P.S。当然,在此问题上,TCPv4协议规范必须说的是什么,以及操作系统实际上在做什么。例如,也许协议是不可知的,但是OS往往只使用单个地址空间?还是不同的操作系统以不同的方式对待问题?
我个人目前对Linux的功能最感兴趣。
答案 0 :(得分:2)
TCP规范说连接由元组标识:
{local addr, local port, remote addr, remote port}
基于此,理论上,在现有连接中使用的本地端口与尝试将同一端口绑定以供服务器侦听之间不应存在冲突,因为侦听套接字没有远程地址/端口(在规范中以通配符表示)。
但是,大多数TCP实现(包括Unix套接字API)都比这更严格。如果本地端口已在任何现有套接字中使用,则将无法绑定该端口,您将收到错误EADDRINUSE
。如果现有的套接字全部都处于TIME_WAIT
状态,并且新套接字具有SO_REUSEADDR
套接字选项,则会发生特殊的异常;这用于允许服务器重新启动,而上一个进程留下的套接字仍在等待超时。
因此,端口范围通常分为不同用途的范围。当套接字未绑定本地端口时(要么是因为它只是调用了connect()
而没有调用bind()
,要么是因为在IPPORT_ANY
中将bind()
指定为端口),则该端口是从 ephemeral 范围中选择的,该范围通常是编号很高的端口。另一方面,服务器应绑定到低编号的端口。如果网络应用程序遵循此约定,则不应发生冲突。