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

同一机器上的两个应用程序可以绑定到相同的端口和IP地址吗?更进一步,一个应用程序可以侦听来自某个IP的请求,而另一个应用程序可以侦听来自另一个远程IP的请求吗? 我知道我可以让一个应用程序启动两个线程(或分支)具有类似的行为,但是两个没有任何共同之处的应用程序也可以这样做吗?< / p >
361660 次浏览

答案取决于所考虑的操作系统。总的来说:

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

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

编辑:自Linux Kernel 3.9及更高版本以来,使用SO_REUSEPORT选项添加了对多个应用程序侦听同一端口的支持。更多信息可访问这是lwn.net的文章。

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

使用多播套接字(听起来与您想要的相距甚远),只要在每个套接字的选项中设置SO_REUSEADDR,就可以有多个应用程序绑定到一个端口。

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

除此之外,我们将讨论细节——您同时标记了TCP和UDP,是哪个?还有,什么平台?

原则上,没有。

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

如果操作系统允许两个应用程序打开同一个端口,它怎么知道该通知哪一个呢?

但是…有一些方法可以解决这个问题:

    就像Jed 指出一样,你可以写一个“主”进程,它将是唯一一个真正侦听端口并通知其他端口的进程,使用任何它想要分离客户端请求的逻辑。
    • 在Linux和BSD(至少)上,你可以设置“重映射”规则,将数据包从“可见”端口重定向到不同的端口(应用程序正在侦听的端口),根据任何与网络相关的标准(可能是原始网络,或一些简单的负载平衡形式)。
    • 李< / ul > < / >

如果至少有一个远程ip是已知的,静态的,专用于只与你的一个应用程序对话,你可以使用iptables规则(表nat,链PREROUTING)来重定向从这个地址到“共享”本地端口的传入流量到任何其他端口,其中适当的应用程序实际监听。

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

SO_REUSEADDR

允许其他套接字bind()到该端口,除非已经有一个活动监听套接字绑定到该端口。这使您能够在崩溃后尝试重新启动服务器时绕过“地址已在使用”错误消息。

是也不是。只有一个应用程序可以在一个端口上进行主动侦听。但是该应用程序可以将其连接遗留给另一个进程。因此,您可以让多个进程在同一个端口上工作。

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

是的。

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

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

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

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

参考资料:Stevens &赖特,TCP / IP了,卷II。

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

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

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

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

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

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

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

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

简短的回答:

根据给出的答案在这里。您可以让两个应用程序侦听相同的IP地址和端口号,只要其中一个端口是UDP端口,而另一个是TCP端口。

解释:

端口的概念与TCP/IP堆栈的传输层相关,因此只要使用堆栈的不同传输层协议,就可以让多个进程侦听相同的<ip-address>:<port>组合。

人们有一个疑问是,如果两个应用程序运行在相同的<ip-address>:<port>组合上,在远程机器上运行的客户端如何区分这两个应用程序?如果你看一下IP层包头(https://en.wikipedia.org/wiki/IPv4#Header),你会发现第72位到第79位是用来定义协议的,这就是如何区分的。

然而,如果你想让两个应用程序在相同的TCP <ip-address>:<port>组合上,那么答案是不(一个有趣的练习是启动两个vm,给它们相同的IP地址,但不同的MAC地址,看看会发生什么——你会注意到有些时候VM1会得到数据包,而其他时候VM2会得到数据包——这取决于ARP缓存刷新)。

我觉得通过让两个应用程序运行在同一个<op-address>:<port>上,你想要达到某种负载平衡。为此,您可以在不同的端口上运行应用程序,并编写IP表规则来划分它们之间的流量。

请参见@user6169806的回答。

我已经用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

是的。

来自这篇文章:
https://lwn.net/Articles/542629/ < / p >

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

在创建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

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

它适用于TCPUDP。更多细节请参考链接:SO_REUSEPORT

只是分享@jnewton提到的内容。 我在我的mac上启动了一个nginx和一个嵌入式tomcat进程。我可以看到两个进程都运行在8080。< / p >
LT<XXXX>-MAC:~ b0<XXX>$ sudo netstat -anp tcp | grep LISTEN
tcp46      0      0  *.8080                 *.*                    LISTEN
tcp4       0      0  *.8080                 *.*                    LISTEN