当应用程序寻找要绑定的端口时,是否会/etc/services
主动搜索以确保不发生冲突?即,如果一个端口在 中注册/etc/services
,那么无论它是否实际使用,它是否都被保留?
答案1
每个 TCP 连接涉及的不是一个,而是二端口号:本地端口和远程端口。在传出连接中,本地端口号并不重要,大多数程序都让操作系统选择它。正如 binsta 所指出的,操作系统将自动选择临时端口范围中的第一个空闲端口。
但是应用程序(或运行应用程序的用户)必须指定要连接的远程端口号,否则它将无法到达远程主机中的正确服务。
对于传入连接,情况是镜像的:服务器应用程序通常不能让操作系统选择用于侦听传入连接的本地端口号,否则客户端将不知道要连接到哪个端口。但是侦听传入连接的应用程序通常会忽略远程端口号并让其由远程主机决定。
(有些服务使用完全动态端口号,通常依赖辅助发现协议来找出服务器正在侦听的端口:NFSv3 rpc.statd
,这rpc.mountd
可能是现代 Linux 用户最熟悉的示例。要在远程主机,您应该首先联系该主机上端口 111 上的 RPC 端口映射器,并询问服务位于哪些端口。)
一些服务器应用程序(主要是经典的 Unix 服务器应用程序,例如inetd
)可能会查找本地端口以按名称使用,getportbyname()
通常只需从/etc/services
.
但应用程序可以跳过此步骤,而是直接按数字指定所需的端口。大多数现代应用程序都倾向于这样做;当然,任何需要您按号码配置侦听端口的服务器程序都会这样做。
如今,更常见的用途/etc/services
可能是诸如lsof
、netstat
或 之类的应用程序tcpdump
,它们可能会将其输出中的端口号替换为从 中查找的更人性化的名称/etc/services
。但您应该记住,这种端口号到名称的查找只能依赖于描述典型用途:它可能是也可能不是对端口的准确描述实际使用在您的特定系统上。
那么对于“如果一个端口在 中注册/etc/services
,它是否被保留?”的问题答案是不,不是。
一些应用程序可以用来/etc/services
确定要使用的端口号,除非端口号是在应用程序配置中直接指定的或由用户指定的。
针对“冲突”的保护发生在操作系统级别,与以下情况完全无关/etc/services
:如果应用程序进行bind(2)
系统调用来指定它想要使用特定的端口号,并且该端口已被其他程序使用,则系统调用将失败出现EADDRINUSE
错误,表明其他东西已经在使用它。
答案2
不,应用程序请求绑定到端口,但实际上是操作系统决定是否将端口分配给应用程序。
因此,例如小于 1024 的端口只能由root
任何CAP_NET_BIND_SERVICE
有能力的用户使用。
proc/sys/net/ipv4/ip_local_port_range
定义 TCP 和 UDP 流量用于选择本地端口的本地端口范围,称为临时端口范围(您可以更改它)
cat /proc/sys/net/ipv4/ip_local_port_range
32768 60999
或者
sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 60999
/proc/sys/net/ipv4/ip_local_reserved_ports
另外,某些端口可以由管理员通过配置或内核参数保留net.ipv4.ip_local_reserved_ports
,因此这些端口将不会被自动端口分配所使用。
目的/etc/services
是让程序可以getportbyname()
在其代码中进行套接字调用,以获取应使用的端口。
答案3
许多应用程序都有称为众所周知的端口号。他们通常会绑定到它。
其他应用程序将绑定到端口0,让系统选择一个空闲端口。然后,他们使用其他方法(除了众所周知的端口号)将其端口号传达给最终客户端。例如,向网络广播它们的可用性。
答案4
需要消化的东西太多了。我想我已经得到了我需要的答案:/etc/services 只是一个众所周知的服务和官方名称的寄存器。可以使用 getportbyname() 直接引用它,但这不是强制性的。当请求动态端口时,可能会请求传出端口。 ip_local_port_range 是允许端口范围的参考。管理员可以通过将某些端口添加到 /proc/sys/net/ipv4/ip_local_reserved_ports 或内核参数 rnet.ipv4.ip_local_reserved_ports 来保留它们。自动端口分配不会使用这些端口。如果我的说法正确,那么我提出这个问题的原因是我已经从安全的 AIX 本地世界转移到了 Azure Cloud 和 SUSE。对于云中的集群,他们使用负载均衡器功能来定义将在集群节点之间移动的服务 IP 地址等。必须为它们指定要使用的特定端口,例如选择 62500。我最近一直在测试一些名为 Commvault 的备份软件,偶尔它会在集群启动之前占用相同的端口,所以我一直在寻找阻止这种情况的方法。看来我要么更改默认的本地端口范围,使高标记为 62499,要么将端口专门添加到 ip_local_reserved_ports 如果我已经得到所有这些正确的信息,非常感谢大家的迅速帮助,