在 Windows 上,这显然是不允许的,你可以用多个 IP 分别绑定同一个 PORT,但是不允许同一个 IP+PORT 被多次绑定。
在 Linux 上,以前也是不允许,但后来修改了内核,从 3.9 开始,TCP 变得和 UDP 一样,可以多个程序同时监听同一个 IP+端口。
这样的话,只要你有服务器 ROOT 权限,开一个和 nginx 一样的 80 端口程序,就可以开心和他抢数据了。
1
hxndg 2021-04-07 14:57:19 +08:00
为啥不允许呢? TCP 五元组啊,只要能在 TCP 上层区分开到底该交给谁,为啥不能绑定同一个端口呢?
我司复杂均衡,自己实现 2-7 层,我们自己维护 PCB,实现的时候完全可以共享端口。 当然前提是 PCB 自己维护,也就是筛选数据包给谁自己维护 |
2
3dwelcome OP @hxndg UDP 我能理解,包是单独的,最终给谁都能直接处理。
可 TCP 是流式数据,怎么切分成小包,是底层决定的,又不是由程序决定的。 比如 HTTP 你程序负载均衡,只拿到用户 HTTP 请求中间那么一小段,也没办法处理啊。 |
3
hxndg 2021-04-07 16:12:27 +08:00
@3dwelcome
首先,负载均衡可以坐在四层也可以坐在七层 其次,你可以自己维护负载均衡,也可以让系统底层维护负载均衡。还是那句话五元组可以区分开具体该交给哪个线程了。 lwn.net 上的介绍 https://lwn.net/Articles/542629/ |
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 |
5
3dwelcome OP @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 五元组冲突) |
6
hxndg 2021-04-08 07:47:31 +08:00 via Android
算了,你说的都对,你开心就好
|
7
3dwelcome OP @hxndg 我只是好奇讨论一下。
一般情况,一台 PC 确实只有 2 万多个客户端连接端口可用(默认 net.ipv4.ip_local_port_range = 32768 61000)。就算不用 IPV4,改用 IPV6,协议也没增加任何端口上限,还是 16bit 给写死了。 所以如果这台 PC,刚巧是 NAT 出口,就会遇到本机端口耗尽的情况。TCP 五元祖冲突应该不会,就是 TCP 连接直接失败。 |
8
julyclyde 2021-04-08 12:15:35 +08:00
能理解你的提问的人都不太多
建议你还是把“3.9 开始”那个功能的原文发上来 |
9
SmartKeyerror 2021-04-08 17:23:54 +08:00
@hxndg 我寻思着 TCP 包里面只包含源端口号+目的端口号,IP 包里面才是源 IP 地址 + 目的 IP 地址,TCP 区分接收程序难道不是通过端口号区分的? TCP 上层是个什么东西?
|
10
hxndg 2021-04-08 17:43:02 +08:00
@SmartKeyerror
四层负载均衡和七层负载均衡的区别,自定协议和非自定协议而已 而且协议栈如果自己写,想干什么干什么,为什么不能拿到五元组呢? 如果只能利用端口号区分,那么多的负载均衡公司都是在扯淡吗? |