TCP server 为什么一个端口可以建立多个连接?

本文探讨了TCP连接机制,解释了为何服务器端口可以接受多个连接,而客户端在同一端口上尝试建立第二个连接时会遇到端口被占用的问题。通过内核五元组的概念,深入解析了TCP连接的唯一性。

https://segmentfault.com/q/1010000003101541

如果是tcp client用同一个本地端口去连不同的两个服务器ip,连第二个时就会提示端口已被占用。但服务器的监听端口,可以accept多次,建立多个socket;我的问题是服务器一个端口为什么能建立多个连接而客户端却不行呢?

 

5个回答

答案对人有帮助,有参考价值 8答案没帮助,是错误的答案,答非所问

已采纳

TCP server 可以,TCP client 也可以。一个套接字只能建立一个连接,无论对于 server 还是 client。

注意报错消息是:

[Errno 106] (EISCONN) Transport endpoint is already connected

man 2 connect 说得很清楚了:

Generally, connection-based protocol sockets may successfully connect() only once; connectionless protocol sockets may use connect() multiple times to change their association.

就是说,TCP 套接字最多只能调用 connect 一次。那么,你的监听套接字调用 connect 了几次?


来点有意思的。

一个套接字不能连接两次,并不代表一个本地地址不能用两次,看!*加粗文字加粗文字*

>>> import socket
>>> s = socket.socket()
# since Linux 3.9, 见 man 7 socket
>>> s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) >>> s2 = socket.socket() >>> s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) >>> s.bind(('127.0.0.1', 12345)) >>> s2.bind(('127.0.0.1', 12345)) # 都可以使用同一本地地址来连接哦 >>> s.connect(('127.0.0.1', 80)) >>> s2.connect(('127.0.0.1', 4321))
>>> netstat -npt | grep 12345
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 127.0.0.1:4321 127.0.0.1:12345 ESTABLISHED 18284/python3 tcp 0 0 127.0.0.1:12345 127.0.0.1:4321 ESTABLISHED 4568/python3 tcp 0 0 127.0.0.1:80 127.0.0.1:12345 ESTABLISHED - tcp 0 0 127.0.0.1:12345 127.0.0.1:80 ESTABLISHED 4568/python3

你们这些有女友的都弱爆了啦 :-(


更新:大家来玩 TCP: 一个人也可以建立 TCP 连接呢 - 依云's Blog

答案对人有帮助,有参考价值 2答案没帮助,是错误的答案,答非所问

内核是以一个(著名的)5元信息组来标识不同的socket的:源地址、源端口、目的地址、目的端口、协议号。任何一个不同,都不叫“同一个socket”。

答案对人有帮助,有参考价值 0答案没帮助,是错误的答案,答非所问

首先,TCP链接是可靠的端对端的链接,每个TCP链接由4个要素组成:2组IP地址(本地和远端),2组端口地址(本地和远端)。其中如果需要跟端口信息绑定时,都需要调用bind函数,如果server端针对2个同样的IP、端口组进行同样的绑定时,第2次同样是不成功的。

答案对人有帮助,有参考价值 0答案没帮助,是错误的答案,答非所问

有个相关的问题: ftp的数据传输,服务器会用20端口主动连接客户端,如果两个客户端同时在一下载东西,那ftp 服务器能用20端口去连接两个ip ?(这时ftp的服务器其实是tcp里的客户端)

能啊,看我的实验。

— 依云 · 2015年08月19日

展开评论
答案对人有帮助,有参考价值 -1答案没帮助,是错误的答案,答非所问

不管是服务器还是客户端,建立TCP链接,同一个端口都只能使用一次。

这句话其实是**错的**!

对于TCP协议,要成功建立一个新的链接,需要保证新链接四个要素组合体的唯一性:客户端的IP、客户端的port、服务器端的IP、服务器端的port。也就是说,服务器端的同一个IP和port,可以和同一个客户端的多个不同端口成功建立多个TCP链接(与多个不同的客户端当然也可以),只要保证【Server IP + Server Port + Client IP + Client Port】这个组合唯一不重复即可。

> netstat -a -n -p tcp |grep 9999
tcp 0 0 127.0.0.1:51113 127.0.0.1:9999 ESTABLISHED 2701/nc tcp 0 0 127.0.0.1:51119 127.0.0.1:9999 ESTABLISHED 2752/nc 

上述结果127.0.0.1:9999中9999端口成功建立两个TCP链接,也就可以理解。

**客户端**发送TCP链接请求的端口,也就是后续建立TCP链接使用的端口,所以一旦TCP链接建立,端口就被占用,无法再建立第二个链接。

而**服务器端**有两类端口:侦听端口 和 后续建立TCP链接的端口。其中侦听端口只负责侦听客户端发送来的TCP链接请求,不用作建立TCP链接使用,一旦侦听到有客户端发送TCP链接请求,就分配一个端口(一般随机分配,且不会重复)用于建立TCP链接,而不是所说的服务器一个端口能建立多个连接

上述描述也比较片面,客户端如何请求及建立链接,服务器端如何侦听及是否分配新随机端口等...应该都可以在应用层面进行控制,所以上述描述可以作为建立TCP链接的一种方式,仅供参考。

一些英文的参考:
How do multiple clients connect simultaneously to one port, say 80, on a server?
TCP : two different sockets sharing a port?

如果真是这样,为什么netstat 命令只看到监听端口而没有你说的另一个随机端口?

— hyanleo · 2015年08月16日

accept 才不会分配新端口号,不然大家不用考虑单机的 C10K 问题了,反正端口号不够用不是?

— 依云 · 2015年08月19日

 

 

 

一个端口**可以参与多个 TCP 连接**,但需要注意的是,**每个连接的五元组必须唯一**。TCP 协议通过 **五元组(源 IP、源端口、目的 IP、目的端口、协议)** 来唯一标识一个连接。 --- ### ✅ 1. **一个端口可以建立多个 TCP 连接吗?** #### ✅ 答案: **是的,一个端口可以同时参与多个 TCP 连接。** #### 🔍 原理: TCP 使用 **五元组(5-tuple)** 来标识一个连接: ``` {源IP地址, 源端口号, 目的IP地址, 目的端口号, 协议} ``` 只要这五个字段的组合不同,就表示不同的连接。 --- ### ✅ 2. **常见场景举例** #### 📌 场景 1:服务器监听同一个端口接收多个客户端连接 - 服务器端口 `80`(HTTP)监听。 - 多个客户端使用不同源 IP 或源端口连接服务器的 `80` 端口。 - 每个连接的五元组不同,因此是独立的连接。 ``` 客户端A:192.168.1.10:54321 → 服务器:192.168.1.1:80 客户端B:192.168.1.11:62345 → 服务器:192.168.1.1:80 ``` #### 📌 场景 2:同一客户端访问同一服务器端口 - 客户端使用不同的源端口连接服务器的同一个端口。 - 源端口不同 → 五元组不同 → 是两个不同的连接。 ``` 客户端:192.168.1.10:54321 → 服务器:192.168.1.1:80 客户端:192.168.1.10:54322 → 服务器:192.168.1.1:80 ``` --- ### ✅ 3. **限制条件** - **同一客户端 IP + 端口 → 同一服务器 IP + 端口**: - 不能建立多个连接,因为五元组完全相同。 - TCP 会认为是重复的连接请求,并丢弃或拒绝。 ``` 客户端:192.168.1.10:54321 → 服务器:192.168.1.1:80(已存在) ``` - **端口冲突**: - 如果一个端口已经被绑定为监听状态(如 Web 服务器监听 80),其他程序不能再绑定该端口,除非使用 `SO_REUSEADDR` 选项。 --- ### ✅ 4. **代码示例(Python 服务器监听多个连接)** ```python import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', 8080)) server_socket.listen(5) print("Listening on port 8080...") while True: client_socket, addr = server_socket.accept() print(f"Connection from {addr}") ``` > 多个客户端可以同时连接到 `8080` 端口,每个连接独立。 --- ### ✅ 5. **总结** | 问题 | 回答 | |------|------| | 一个端口可以有多个 TCP 连接吗? | ✅ 可以 | | 多个连接如何区分? | 通过五元组唯一标识 | | 同一客户端可以多次连接同一端口吗? | ✅ 只要源端口不同即可 | | 五元组相同能建立多个连接吗? | ❌ 不允许,连接会被拒绝 | | 服务器端口如何支持高并发? | 使用多线程、异步 IO、epoll 等机制处理多个连接 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值