同一台机器上的两个应用程序可以绑定到同一个端口和IP地址吗?更进一步,一个应用程序可以收听来自某个IP和另一个远程IP的请求吗?我知道我可以有一个应用程序从两个线程(或叉子)开始有类似的行为,但两个没有任何共同点的应用程序可以做同样的事情吗?
对于TCP,没有。一次只能有一个应用程序在同一端口上进行侦听。现在,如果你有2个网卡,你可以让一个应用程序在第一个IP上侦听,第二个在第二个IP上使用相同的端口号。
对于UDP(多播),多个应用程序可以订阅同一端口。
创建TCP连接时,要求连接到特定的TCP地址,该地址是IP地址(v4或v6,具体取决于您使用的协议)和端口的组合。
当服务器侦听连接时,它可以通知内核它想要侦听特定的IP地址和端口,即一个TCP地址,或者每个主机的IP地址上的同一端口(通常用IP地址指定) 0.0.0.0
),它有效地监听了许多不同的“TCP地址”(例如,192.168.1.10:8000
,127.0.0.1:8000
等)
不,你不能让两个应用程序监听相同的“TCP地址”,因为当一条消息进来时,内核如何知道给哪个应用程序提供消息?
但是,在大多数操作系统中,您可以在单个界面上设置多个IP地址(例如,如果您在界面上有192.168.1.10
,您也可以设置192.168.1.11
,如果网络上没有其他人使用它),以及在这两种IP地址中,您可以使用单独的应用程序侦听端口8000
。
是的,不是。只有一个应用程序可以主动侦听端口。但是该应用程序可以将其与另一个进程的连接遗留下来。因此,您可以在同一端口上运行多个进程。
如果应用程序你的意思是多个进程然后是,但通常是NO。例如,Apache服务器在同一端口(通常为80)上运行多个进程。通过指定一个实际绑定到端口的进程然后使用该进程切换到接受连接的各个进程来完成。
您可以使两个应用程序在同一网络接口上侦听同一端口。
指定的网络接口和端口只能有一个侦听套接字,但该套接字可以在多个应用程序之间共享。
如果你在一个应用程序进程中有一个监听套接字而你正在进行fork
处理,那么套接字将被继承,所以从技术上讲,现在将有两个进程监听同一个端口。
我用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
只是为了分享@jnewton提到的内容。我在我的mac上启动了一个nginx和一个嵌入式tomcat进程。我可以看到两个流程都在8080运行。
LT<XXXX>-MAC:~ b0<XXX>$ sudo netstat -anp tcp | grep LISTEN
tcp46 0 0 *.8080 *.* LISTEN
tcp4 0 0 *.8080 *.* LISTEN
简短回答:
按照here给出的答案。您可以让两个应用程序侦听相同的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>
组合上有两个应用程序,那么答案是否定的(一个有趣的练习是启动两个虚拟机,给它们相同的IP地址,但不同的MAC地址,看看会发生什么 - 你会注意到一些时间VM1将获取数据包,其他时间VM2将获取数据包 - 取决于ARP缓存刷新)。
我觉得通过使两个应用程序在相同的<op-address>:<port>
上运行,您希望实现某种负载平衡。为此,您可以在不同的端口上运行应用程序,并编写IP表规则以分隔它们之间的流量。
另见@ user6169806的答案。
是(对于TCP),如果程序设计为可以,则可以在同一个套接字上侦听两个程序。当套接字由第一个程序创建时,请确保在SO_REUSEADDR
之前在套接字上设置了bind()
选项。但是,这可能不是你想要的。这样做的是传入的TCP连接将被定向到其中一个程序,而不是两个,因此它不会复制连接,它只允许两个程序为传入的请求提供服务。例如,Web服务器将有多个进程都在端口80上进行侦听,并且O / S会向准备接受新连接的进程发送新连接。
SO_REUSEADDR
允许其他套接字到bind()
到此端口,除非已经绑定到端口的活动侦听套接字。这使您可以在崩溃后尝试重新启动服务器时绕过那些“已在使用中的地址”错误消息。
原则上,没有。
它不是一成不变的;但它是所有API编写的方式:应用程序打开一个端口,获取它的句柄,当客户端连接(或UDP情况下的数据包)到达时,操作系统通知它(通过该句柄)。
如果操作系统允许两个应用程序打开同一个端口,它将如何知道要通知哪个?
但是......有很多方法可以解决它:
是。
0.0.0.0
(INADDR_ANY
)。SO_REUSEADDR
选项。参考:Stevens&Wright,TCP / IP Illustrated,第二卷。
当然是。据我记得从内核版本3.9(不确定版本)开始对SO_REUSEPORT
的支持。 SO_RESUEPORT
允许绑定到完全相同的端口和地址,只要第一个服务器在绑定其套接字之前设置此选项。
它适用于TCP和UDP。有关更多详细信息,请参阅链接:SO_REUSEPORT
注意:根据我的观点,接受的答案不再适用。
不可以。一次只能有一个应用程序绑定到端口,并且强制绑定时的行为是不确定的。
使用多播套接字 - 听起来不像您想要的那样 - 只要在每个套接字的选项中设置了SO_REUSEADDR,多个应用程序就可以绑定到端口。
您可以通过编写一个“主”进程来完成此操作,该进程接受并处理所有连接,然后将它们交给需要在同一端口上侦听的两个应用程序。这是Web服务器等采取的方法,因为许多进程需要监听80。
除此之外,我们进入细节 - 你标记了TCP和UDP,它是什么?还有什么平台?
您可以让一个应用程序在一个端口上侦听一个网络接口。因此你可以:
httpd
收听远程访问界面,例如192.168.1.1:80
127.0.0.1:80
的守护进程示例用例可以是使用httpd
作为负载均衡器或代理。
另一种方法是使用一个程序监听一个端口,该程序分析它在内部重定向到“真实”服务正在侦听的另一个端口的流量类型(ssh,https等)。
例如,对于Linux,sslh:https://github.com/yrutschle/sslh
如果至少有一个远程IP已知,静态且专用于与您的某个应用程序通信,则可以使用iptables规则(表nat,链PREROUTING)将来自此地址的流量重定向到“共享”本地端口适当的应用程序实际收听的任何其他端口。