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

本文介绍了TCP套接字的基本概念,包括一个套接字只能建立一个连接的原则,并解释了如何通过设置SO_REUSEPORT选项使多个套接字能够绑定到同一个本地地址上,同时还展示了如何使用Python进行具体操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自segment fault
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 45
在Unity中进行TCP通讯时,同一个IP地址可以使用不同的端口号来建立不同的连接TCP协议是基于连接的协议,每个连接一个四元组(源IP地址,源端口号,目标IP地址,目标端口号)唯一标识。因此,即使目标IP地址相同,只要使用不同的端口号,就可以建立多个独立的连接。 具体步骤如下: 1. **创建Socket对象**:使用`System.Net.Sockets.Socket`类来创建TCP连接。 2. **绑定端口号**:在客户端,可以通过`Socket.Bind`方法绑定到特定的本地端口号(可选)。在服务器端,通常需要绑定到一个特定的端口号来监听连接请求。 3. **建立连接**:使用`Socket.Connect`方法在客户端建立连接,或使用`Socket.Accept`方法在服务器端接受连接请求。 以下是一个简单的示例代码,展示了如何在Unity中使用不同的端口建立多个TCP连接: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine; public class TCPConnectionExample : MonoBehaviour { void Start() { // 服务器端示例 StartServer(); // 客户端示例 StartClient("127.0.0.1", 8000); StartClient("127.0.0.1", 8001); } void StartServer() { Thread serverThread = new Thread(() => { TcpListener listener = new TcpListener(IPAddress.Any, 8000); listener.Start(); Debug.Log("Server started, waiting for connections..."); while (true) { TcpClient client = listener.AcceptTcpClient(); Debug.Log("Client connected!"); NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024]; int byteCount = stream.Read(buffer, 0, buffer.Length); string data = Encoding.ASCII.GetString(buffer, 0, byteCount); Debug.Log("Received data: " + data); string response = "Hello from server!"; byte[] responseBytes = Encoding.ASCII.GetBytes(response); stream.Write(responseBytes, 0, responseBytes.Length); client.Close(); } }); serverThread.IsBackground = true; serverThread.Start(); } void StartClient(string serverIP, int serverPort) { Thread clientThread = new Thread(() => { TcpClient client = new TcpClient(); client.Connect(serverIP, serverPort); Debug.Log("Connected to server!"); NetworkStream stream = client.GetStream(); string message = "Hello from client!"; byte[] data = Encoding.ASCII.GetBytes(message); stream.Write(data, 0, data.Length); Debug.Log("Sent data: " + message); byte[] buffer = new byte[1024]; int byteCount = stream.Read(buffer, 0, buffer.Length); string response = Encoding.ASCII.GetString(buffer, 0, byteCount); Debug.Log("Received response: " + response); client.Close(); }); clientThread.IsBackground = true; clientThread.Start(); } } ``` 在这个示例中,服务器端监听8000端口,而客户端分别连接到8000和8001端口,从而展示了同一个IP可以使用不同的端口建立不同的连接
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值