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

时间:2009-11-07 19:32:23

标签: sockets tcp udp port communication

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

16 个答案:

答案 0 :(得分:225)

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

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

答案 1 :(得分:110)

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

SO_REUSEADDR

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

答案 2 :(得分:46)

原则上,没有。

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

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

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

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

答案 3 :(得分:43)

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

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

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

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

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

答案 4 :(得分:23)

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

适用于 TCP UDP 。有关详细信息,请参阅该链接:SO_REUSEPORT

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

答案 5 :(得分:18)

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

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

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

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

答案 6 :(得分:3)

另一种方法是使用在一个端口中侦听的程序,该程序分析流量类型(ssh,https等),将其内部重定向到“真正”服务正在侦听的另一个端口。

例如,对于Linux,sslh:https://github.com/yrutschle/sslh

答案 7 :(得分:3)

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

  1. httpd收听远程访问界面,例如192.168.1.1:80
  2. 另一个守护着127.0.0.1:80
  3. 的守护进程

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

答案 8 :(得分:2)

如果至少有一个远程IP已知,静态且专用于与您的某个应用程序通信,则可以使用iptables规则(表nat,链PREROUTING)将来自此地址的流量重定向到“共享”本地端口到相应应用程序实际侦听的任何其他端口。

答案 9 :(得分:2)

当您创建TCP连接时,您要求连接到特定的TCP地址,该地址是IP地址(v4或v6,具体取决于您正在使用的协议)和端口的组合。

当服务器侦听连接时,它可以通知内核它想要监听特定的IP地址和端口,即一个TCP地址,或者在每个主机的IP上的同一端口上地址(通常用IP地址0.0.0.0指定),它有效地监听许多不同的" TCP地址" (例如,192.168.1.10:8000127.0.0.1:8000等。)

不,你不能让两个应用程序监听相同的" TCP地址,"因为当一条消息进来时,内核将如何知道哪个应用程序提供消息?

但是,在大多数操作系统中,您可以在一个界面上设置多个IP地址(例如,如果您在界面上有192.168.1.10,那么您也可以设置192.168.1.11,如果没有其他人在网络上正在使用它),在这些情况下,您可以让单独的应用程序在这两个IP地址的每一个上侦听端口8000

答案 10 :(得分:1)

是和否。只有一个应用程序可以主动侦听端口。但是该应用程序可以将其与另一个进程的连接遗留下来。因此,您可以在同一端口上运行多个进程。

答案 11 :(得分:1)

从这篇文章:
https://lwn.net/Articles/542629/

  

新的套接字选项允许同一主机上的多个套接字绑定到同一端口

答案 12 :(得分:0)

如果应用程序是指多个进程,那么是,但通常为NO。  例如,Apache服务器在同一端口(通常为80)上运行多个进程。通过指定一个实际绑定到端口的进程然后使用该进程切换到接受连接的各个进程来完成。

答案 13 :(得分:0)

您可以让两个应用程序在同一个网络接口上侦听同一个端口。

指定的网络接口和端口只能有一个侦听套接字,但该套接字可以在多个应用程序之间共享。

如果你在一个应用程序进程中有一个侦听套接字而你fork那个进程,套接字将被继承,所以从技术上讲,现在有两个进程在监听同一个端口。

答案 14 :(得分:0)

我使用socat尝试了以下内容:

socat TCP-L:8080,fork,reuseaddr -

即使我没有连接到套接字,我也不能在同一个端口上听两次,尽管有reuseaddr选项。

我收到此消息(我之前预期):

2016/02/23 09:56:49 socat[2667] E bind(5, {AF=2 0.0.0.0:8080}, 16): Address already in use

答案 15 :(得分:0)

只需分享@jnewton提到的内容即可。 我在Mac上启动了nginx和嵌入式tomcat进程。我可以在8080看到两个进程runninng。

LT<XXXX>-MAC:~ b0<XXX>$ sudo netstat -anp tcp | grep LISTEN
tcp46      0      0  *.8080                 *.*                    LISTEN     
tcp4       0      0  *.8080                 *.*                    LISTEN