两个应用程序可以侦听同一个端口吗?

nad*_*div 262 sockets port udp tcp communication

同一台机器上的两个应用程序可以绑定到同一个端口和IP地址吗?更进一步,一个应用程序可以收听来自某个IP和另一个远程IP的请求吗?我知道我可以有一个应用程序从两个线程(或叉子)开始有类似的行为,但两个没有任何共同点的应用程序可以做同样的事情吗?

Chr*_*ail 235

对于TCP,没有.一次只能有一个应用程序在同一端口上进行侦听.现在,如果你有2个网卡,你可以让一个应用程序在第一个IP上侦听,第二个在第二个IP上使用相同的端口号.

对于UDP(多播),多个应用程序可以订阅同一端口.

  • 每个IP地址每个端口一个侦听器.添加另一个网络接口是获取第二个IP地址的一种方法.您的平台可能支持虚拟接口,这是通过一个物理网卡获取两个IP地址的另一种方法. (42认同)
  • "一个应用程序侦听单个端口"这就是端口存在的原因 - 允许多个应用程序共享网络而不会发生冲突. (19认同)
  • **对于UDP(多播),多个应用程序可以订阅同一个端口.**如果一个数据包已从客户端到达,哪个应用程序接收它? (12认同)
  • 虽然到目前为止我的意见相同,但事实证明我能够将两个不同的进程绑定到同一个ip和TCP端口!如果在绑定到Java之前在Java中设置ServerSocket.setReuseAddress(true),则可以执行此操作.真意外的行为. (7认同)
  • (1)你的答案的实际含义是'For TCP,*yes,*provided ...'(2)组播不是UDP端口共享的前提条件,但是SO_REUSEADDR是. (7认同)
  • @Eugen还注意到Java bug [7179799](http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7179799),这可能发生在具有多个Java版本的Windows上. (2认同)
  • @Chris,此答案具有误导性,应进行编辑/删除。 (2认同)

小智 117

是(对于TCP),如果程序设计为可以,则可以在同一个套接字上侦听两个程序.当套接字由第一个程序创建时,请确保SO_REUSEADDR在您之前在套接字上设置该选项bind().但是,这可能不是你想要的.这样做的是传入的TCP连接将被定向到其中一个程序,而不是两个,因此它不会复制连接,它只允许两个程序为传入的请求提供服务.例如,Web服务器将有多个进程都在端口80上进行侦听,并且O/S会向准备接受新连接的进程发送新连接.

SO_REUSEADDR
Run Code Online (Sandbox Code Playgroud)

允许其他套接字bind()到此端口,除非已有绑定到端口的活动侦听套接字.这使您可以在崩溃后尝试重新启动服务器时绕过那些"已在使用中的地址"错误消息.

  • 这个答案是不正确的,除非所有的插座被绑定到不同的IP地址,其中没有一个是INADDR_ANY,或除非你是在Windows上,这里的结果是不确定的. (3认同)
  • 当然,至少在Unix上,“ SO_REUSEADDR”不允许您同时使两个TCP套接字处于侦听状态。它的意思是避开“ TIME_WAIT状态”:http://www.unixguide.net/network/socketfaq/4.5.shtml。它可能在Windows上可以运行,但不能保证无论如何该请求都会到达正确的服务器。 (3认同)
  • 您能否详细说明数据如何传输到同一端口上的特定应用程序?当应用程序使用 SO_REUSEADDR 或 SO_REUSEPORT 时,是否需要考虑任何安全问题? (2认同)

Jav*_*ier 47

原则上,没有.

它不是一成不变的; 但它是所有API编写的方式:应用程序打开一个端口,获取它的句柄,当客户端连接(或UDP情况下的数据包)到达时,操作系统通知它(通过该句柄).

如果操作系统允许两个应用程序打开同一个端口,它将如何知道要通知哪个?

但是......有很多方法可以解决它:

  1. 正如Jed所指出的那样,你可以编写一个"主"进程,它将是唯一真正侦听端口并通知其他人的进程,使用它想要分离客户端请求的任何逻辑.
    • 在Linux和BSD(至少)上,您可以设置"重新映射"规则,根据任何网络相关标准(可能是原始网络,或某些网络),将数据包从"可见"端口重定向到不同的端口(应用正在侦听的位置)简单的负载均衡形式).

  • `iptables -m statistic --mode random --probability 0.5`很有趣. (37认同)
  • 这个答案不能被认为是正确的.它完全忽略了SO_REUSEADDR和SO_REUSEPORT的存在. (7认同)
  • @Samuel:打开一个端口(在服务器模式下)意味着获取文件描述符,当系统获得一个SYN数据包到该端口号时,用SYN + ACK响应并在相关的文件描述符上生成一个事件.应用程序使用accept()调用响应该事件,该调用创建与特定流关联的新文件描述符,使原始服务器描述符可以自由获取来自客户端的新连接 (4认同)
  • “打开一个端口”到底是什么意思?我明白这句话,但你知道系统在打开一个端口并处理它时究竟做了什么吗?我知道当你想用 TCP 打开一个端口时,你会得到一个流,这个流是你与远程的连接,但我在网上搜索并没有找到很好的解释。 (2认同)

use*_*421 46

是.

  1. 多个侦听TCP套接字都可以共存,只要它们都绑定到不同的本地IP地址,它们都可以共存.客户可以连接到他们需要的任何一个.这不包括0.0.0.0(INADDR_ANY).

  2. 多个接受的套接字可以共存,所有套接字都可以从同一个侦听套接字接收,所有套接字都显示与侦听套接字相同的本地端口号.

  3. 所有绑定到同一端口的多个UDP套接字都可以共存,提供与(1)相同的条件,或者它们都SO_REUSEADDR在绑定之前设置了选项.

  4. TCP端口和UDP端口占用不同的命名空间,因此使用TCP端口并不排除它用于UDP,反之亦然.

参考:Stevens&Wright,TCP/IP Illustrated,第二卷.


piy*_*ush 25

是肯定的.据我记得从内核版本3.9(不确定版本)开始支持SO_REUSEPORT.SO_RESUEPORT允许绑定到完全相同的端口和地址,只要第一个服务器在绑定其套接字之前设置此选项.

它适用于TCPUDP.有关更多详细信息,请参阅链接:SO_REUSEPORT

注意:根据我的观点,接受的答案不再适用.

  • @Staszek Wireshark不听端口.它在数据包级别运行. (5认同)
  • 完全正确.如果不是这样,Wireshark如何运作? (2认同)

Jed*_*ith 18

不可以.一次只能有一个应用程序绑定到端口,并且强制绑定时的行为是不确定的.

使用多播套接字 - 听起来不像您想要的那样 - 只要在每个套接字的选项中设置了SO_REUSEADDR,多个应用程序就可以绑定到端口.

您可以通过编写一个"主"进程来完成此操作,该进程接受并处理所有连接,然后将它们交给需要在同一端口上侦听的两个应用程序.这是Web服务器等采取的方法,因为许多进程需要监听80.

除此之外,我们进入细节 - 你标记了TCP和UDP,它是什么?还有什么平台?

  • 没有多播套接字这样的东西.有UDP套接字.多播不是SO_REUSEADDR的先决条件. (8认同)

Tom*_*cek 5

您可以让一个应用程序侦听一个网络接口的一个端口。因此你可以:

  1. httpd监听远程访问接口,例如192.168.1.1:80
  2. 另一个守护进程正在监听127.0.0.1:80

示例用例可以用作httpd负载均衡器或代理。