为什么 TCP 允许多个程序绑定同一个 IP 和端口? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
3dwelcome
V2EX    问与答

为什么 TCP 允许多个程序绑定同一个 IP 和端口?

  •  
  •   3dwelcome 2021-04-07 14:48:36 +08:00 1477 次点击
    这是一个创建于 1694 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 Windows 上,这显然是不允许的,你可以用多个 IP 分别绑定同一个 PORT,但是不允许同一个 IP+PORT 被多次绑定。

    在 Linux 上,以前也是不允许,但后来修改了内核,从 3.9 开始,TCP 变得和 UDP 一样,可以多个程序同时监听同一个 IP+端口。

    这样的话,只要你有服务器 ROOT 权限,开一个和 nginx 一样的 80 端口程序,就可以开心和他抢数据了。

    10 条回复    2021-04-08 17:43:02 +08:00
    hxndg
        1
    hxndg  
       2021-04-07 14:57:19 +08:00
    为啥不允许呢? TCP 五元组啊,只要能在 TCP 上层区分开到底该交给谁,为啥不能绑定同一个端口呢?
    我司复杂均衡,自己实现 2-7 层,我们自己维护 PCB,实现的时候完全可以共享端口。
    当然前提是 PCB 自己维护,也就是筛选数据包给谁自己维护
    3dwelcome
        2
    3dwelcome  
    OP
       2021-04-07 15:16:05 +08:00
    @hxndg UDP 我能理解,包是单独的,最终给谁都能直接处理。
    可 TCP 是流式数据,怎么切分成小包,是底层决定的,又不是由程序决定的。
    比如 HTTP 你程序负载均衡,只拿到用户 HTTP 请求中间那么一小段,也没办法处理啊。
    hxndg
        3
    hxndg  
       2021-04-07 16:12:27 +08:00
    @3dwelcome
    首先,负载均衡可以坐在四层也可以坐在七层
    其次,你可以自己维护负载均衡,也可以让系统底层维护负载均衡。还是那句话五元组可以区分开具体该交给哪个线程了。
    lwn.net 上的介绍 https://lwn.net/Articles/542629/
    hxndg
        4
    hxndg  
       2021-04-07 16:15:28 +08:00
    你搞混了两个概念,一个是 TCP 的分包,一个是负载均衡。两个是完全不同的概念
    直接看这个网址吧,说的够简单了 https://medium.com/uckey/so-reuseport-addr-2-2-how-packets-forwarded-to-multiple-sockets-ce4b83cd0fd2
    3dwelcome
        5
    3dwelcome  
    OP
       2021-04-08 01:02:49 +08:00
    @hxndg "还是那句话,TCP 五元组可以区分开具体该交给哪个线程了。"
    不对啊。
    我百度搜了一下,五元祖就是源 IP+源端口+目标 IP+目标端口,可并不是唯一的,很容易就被中间 NAT 修改了( https://www.liangzl.com/get-article-detail-227271.html)

    那么很有可能,到具体线程里,两条不同 TCP 通道,源 IP+源端口+目标 IP+目标端口是一样的。
    首先 SO_REUSEPORT 会确保在多条 TCP 通道里,本机 IP 和本地绑定端口是一致的。
    其次 NAT 下面多条 TCP 通道里,发起 IP 和发起的端口是有可能冲突的(端口只有双字节上限,而 NAT 下面可以扩展很多电脑,每台电脑对相同服务器端口发出请求,总有电脑总连接数超过 65535,就必然会造成 TCP 五元组冲突)
    hxndg
        6
    hxndg  
       2021-04-08 07:47:31 +08:00 via Android
    算了,你说的都对,你开心就好
    3dwelcome
        7
    3dwelcome  
    OP
       2021-04-08 09:49:04 +08:00
    @hxndg 我只是好奇讨论一下。
    一般情况,一台 PC 确实只有 2 万多个客户端连接端口可用(默认 net.ipv4.ip_local_port_range = 32768 61000)。就算不用 IPV4,改用 IPV6,协议也没增加任何端口上限,还是 16bit 给写死了。
    所以如果这台 PC,刚巧是 NAT 出口,就会遇到本机端口耗尽的情况。TCP 五元祖冲突应该不会,就是 TCP 连接直接失败。
    julyclyde
        8
    julyclyde  
       2021-04-08 12:15:35 +08:00
    能理解你的提问的人都不太多
    建议你还是把“3.9 开始”那个功能的原文发上来
    SmartKeyerror
        9
    SmartKeyerror  
       2021-04-08 17:23:54 +08:00
    @hxndg 我寻思着 TCP 包里面只包含源端口号+目的端口号,IP 包里面才是源 IP 地址 + 目的 IP 地址,TCP 区分接收程序难道不是通过端口号区分的? TCP 上层是个什么东西?
    hxndg
        10
    hxndg  
       2021-04-08 17:43:02 +08:00
    @SmartKeyerror
    四层负载均衡和七层负载均衡的区别,自定协议和非自定协议而已
    而且协议栈如果自己写,想干什么干什么,为什么不能拿到五元组呢?
    如果只能利用端口号区分,那么多的负载均衡公司都是在扯淡吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5271 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 07:05 PVG 15:05 LAX 23:05 JFK 02:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86