我正在使用套接字和Java编写聊天程序,并且必须指定服务器侦听的端口。
这是我的问题:
如何确定该端口始终是空闲的?
是否另一个程序也在该端口上监听也有关系吗?
如果端口必须是空闲的并且默认端口已占用,则如何 我可以将端口号更改通知客户吗?
我应该做到这一点,以便服务器不断尝试绑定到新的 端口,增加端口号直到找到可用端口?
答案 0 :(得分:5)
如何确定该端口始终是空闲的?
您可以使用“ netstat”检查端口是否可用。 您可以通过以下方式列出服务正在使用的所有端口:
netstat -anp
如果要搜索特定端口,可以使用:
netstat -anp | find "port number"
,例如netstat -anp | find ":8080"
。
另一个程序是否也在该端口上监听也可以吗?
从传统的角度看,是的,对于TCP,您一次只能让一个应用程序侦听相同的端口和相同的本地IP地址。通过使用多个网卡或虚拟网络接口,可以通过具有多个本地IP地址来使用同一端口。
但是,似乎可以使用SO_REUSEPORT
套接字选项来重用它,请检查this以获得更多信息。
如果端口必须是空闲的并且默认端口已被占用,我如何通知客户端端口号的更改?我是否应该这样做,以便服务器继续尝试绑定到新端口,增加端口号直到找到可用端口?
我个人可以选择一个始终免费的端口,也可以选择一小部分我知道通常可以免费使用的端口,然后逐个尝试。
选择端口的一般经验法则包括至少选择一个4位数字,并避免使用1024以下的数字。 同样,即使该端口已被其他服务使用,您也可以重新分配该端口以监听另一个端口,毕竟它是您的您的网络。
答案 1 :(得分:4)
能否请您描述您要构建的体系结构?您在哪里运行服务器和客户端?
我的建议是:
使用单个恒定端口并配置Web服务器(例如-nginx)以根据域将请求路由到该端口。客户端不必知道端口-仅域。 除此之外,这将不允许所有端口都暴露给网络-仅暴露那些需要的端口(80、443)。
在启动时尝试检测空闲端口(调用netstat或仅递增端口号直到服务启动),然后将端口号存储在本地文件中。使用网络服务器发送此本地文件-例如nginx-始终为80或443端口-作为静态数据。客户端将首先通过静态URL获取端口号,然后连接到提供的端口。
使用名称服务-例如-Spring Cloud-在单独的服务器上运行。在应用程序启动时发现可用端口,并在命名服务中注册它。客户将始终首先请求命名服务。另外,您也可以只使用一个简单的平衡器(例如AWS Elastic Balancer + AWC EC2)。
使用Kubernetes-在特定端口上配置“服务”,并在Pod中运行任意数量的应用程序实例-空闲端口将被自动检测到。
P.s。您不能在单个端口上运行多个应用程序。很有可能甚至不会开始。
答案 2 :(得分:2)
如果正在运行程序的服务器是 服务器,则您应该确定要使用的端口并确保其可用(即未被其他程序使用)。要进行检查,只需尝试在该端口上bind()
ServerSocket
。如果您收到IOException
,则说明该端口可能已在使用中(对于Linux,请检查netstat -anp | grep <port>
的输出以查看正在使用哪个程序)。
如果您不想/不能使用固定端口,则始终可以绑定到端口0
,它将自动分配一个空闲端口。然后,您可以使用getLocalPort()
获取分配的端口。
但是,为了使客户端能够连接到您的服务器(该服务器在“浮动”端口上运行),您需要进行广告宣传,例如到JNDI(在Java中首选),LDAP,...(例如,请参见@Azee answer)。
请注意,TCP选项SO_REUSEADDR
/ SO_REUSEPORT
do not have the same meaning取决于您使用的OS(更不用说它们的(不)可用性)。
答案 3 :(得分:1)
您可以在IANA上注册您的端口。这是已经使用的端口的列表。
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
您可能会认为
嘿,我只有一个人!我不想威胁国际权威!
请记住:
2031
,注册端口的人是私人用户,甚至不是程序员(也许今天已经死了)。