如何知道程序监听哪个端口

How to know what port to have a program listen on

我正在使用套接字和 Java 编写聊天程序,我必须指定服务器侦听的端口。

这是我的问题:

  1. 如何确定该端口始终可用?

  2. 如果另一个程序也在该端口上侦听是否重要?

  3. 如果端口必须空闲,默认端口被占用,怎么办 我会通知客户端口号的变化吗?

  4. 我是否应该让服务器一直尝试绑定到一个新的 端口,递增端口号直到找到空闲端口?

How can I be sure that that port is always free?

您可以使用"netstat" 来检查端口是否可用。 您可以通过以下方式列出服务正在使用的所有端口:

netstat -anp

如果要搜索特定端口,可以使用:

netstat -anp | find "port number",例如netstat -anp | find ":8080".

Does it matter if another program is also listening on that port?

从传统的角度来看,是的,对于 TCP,您一次只能让一个应用程序侦听同一端口和同一本地 IP 地址。通过使用多个网卡或虚拟网络接口,您可以通过拥有多个本地 IP 地址来使用同一端口。

但是,使用 SO_REUSEPORT 套接字选项似乎可以重用它,请查看 this 了解更多信息。

If the port has to be free and the default port is occupied, how would I notify the clients of a change in port number? Should I just make it so the server keeps trying to bind to a new port, incrementing the port number until it finds a free port?

就我个人而言,我要么选择一个始终空闲的端口,要么选择一小部分我知道通常空闲的端口,然后一个一个地尝试。

选择端口的一般经验法则包括至少选择一个 4 位数字并避免低于 1024 的数字。 此外,即使该端口已被其他服务使用,您也可以重新分配它以监听另一个端口,毕竟是 您的 网络。

在 IANA 注册

您可以在 IANA 注册您的端口。这是已使用端口的列表。

https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt

你可能会想

hey, I am a single person only! I dont like to threat a international authority!

请记住:

  1. 90% 的端口是 unassigned/reserved。
  2. 网站http://mobrien.com/注册了端口2031,注册端口的人是个人,甚至不是程序员(也许今天已经死了)。

能否描述一下您要构建的架构?您 运行 您的服务器和客户端在哪里?

我的建议是:

  1. 使用单一常量端口并配置网络服务器(例如 - nginx)以根据域将请求路由到该端口。客户不必知道端口 - 仅域。 除此之外,这将允许不向网络公开所有端口 - 只有那些需要的端口 (80, 443)。

  2. 启动时尝试检测空闲端口(调用 netstat 或增加端口号直到服务启动),将端口号存储在本地文件中。使用网络服务器发送此本地文件 - 例如nginx - 总是 80 或 443 端口 - 作为静态数据。客户端将首先通过静态 url 获取端口号,然后连接到提供的端口。

  3. 使用名称服务 - 例如- Spring 云 - 运行 它在单独的服务器上。在应用程序启动时发现空闲端口,并将其注册到命名服务中。客户总是首先请求命名服务。或者,您可以只使用一个简单的平衡器(例如 AWS Elastic Balancer + AWC EC2)。

  4. 使用 Kubernetes - 在特定端口上配置 "Service" 并在 pods 中配置 运行 任意数量的应用程序实例 - 将自动检测空闲端口。

P.s。您不能在一个端口上 运行 多个应用程序。很可能它甚至不会启动。

如果程序运行在你的服务器上,他们应该决定使用哪个端口并确保它可用(即未被其他程序使用)。要检查这一点,只需尝试 bind() 你的 ServerSocket 在该端口上。如果您得到 IOException,该端口可能已被使用(使用 Linux,检查 netstat -anp | grep <port> 的输出以检查哪个程序正在使用它)。

如果您不想to/cannot使用固定端口,那么您可以随时绑定到端口0,它会自动分配一个空闲端口。然后你可以用 getLocalPort().

得到分配的端口

但是,为了让客户端能够连接到您的服务器(在 "floating" 端口上的 运行),您需要对其进行通告,例如通过 JNDI (preferred in Java), LDAP, ... (see 例如)。

作为旁注,请注意 TCP 选项 SO_REUSEADDR / SO_REUSEPORT do not have the same meaning,具体取决于您使用的 OS(更不用说它们的 (un )可用性).