首页 文章

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

提问于
浏览
226

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

16 回答

  • 215

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

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

  • 45

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

    SO_REUSEADDR
    

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

  • 3

    原则上,没有 .

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

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

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

    • 作为Jed noted,您可以编写一个'master'进程,它将是唯一一个真正侦听端口并通知其他人使用它想要分离客户端请求的任何逻辑的进程 .

    • 在Linux和BSD(至少)上,您可以设置'remapping'规则,根据任何网络相关标准(可能是原始网络,或者某些简单形式的网络),将数据包从'visible'端口重定向到不同的(应用正在侦听的位置) . 负载均衡) .

  • -1

    是 .

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

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

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

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

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

  • 91

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

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

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

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

  • 1

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

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

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

  • 0

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

    • httpd 在远程可访问的界面上进行监听,例如 192.168.1.1:80

    • 另一个监听 127.0.0.1:80 的守护进程

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

  • 1

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

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

  • 18

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

  • 1

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

  • 42

    是 .

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

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

  • 0

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

    当服务器侦听连接时,它可以通知内核它想要侦听特定端口上的特定IP地址和端口(即一个IP地址)或所有主机IP地址,这是有效的听很多不同的“TCP地址”(例如,192.168.1.10:8000,127.0.0.1:8000等)

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

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

  • 14

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

  • 0

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

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

    如果您在应用程序进程中有一个侦听套接字并且您正在进行该进程,则套接字将被继承,因此从技术上讲,现在将有两个进程侦听同一端口 .

  • 3

    我用 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
    
  • 2

    Short answer:

    按照给出的答案here . 您可以让两个应用程序侦听相同的IP地址和端口号,因此端口中的一个端口是UDP端口,而另一个端口是TCP端口 .

    Explanation:

    端口的概念与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> 上运行,您希望实现某种负载 balancer . 为此,您可以在不同的端口上运行应用程序,并编写IP表规则以分隔它们之间的流量 .

    另见@ user6169806的答案 .

相关问题