C# 中具有相同本地端口的多个 TcpClient
Multiple TcpClients with same local port in C#
我正在开发一个点对点文件共享应用程序,无需中央服务器即可用于传输文件。
在一对一文件传输方面,它就像一个魅力,但我最初计划的方式是,发件人可以将文件发送给多个客户端。
该应用程序使用 TCP 打孔,因此不需要端口转发。问题是,为了使 TCP 打洞工作,我需要为每个 TCPClient 指定一个本地端口。因此,我需要绑定套接字。
TCPClient client = new TCPClient(port);
问题是,在创建新客户端时(建立连接后),我会收到错误消息,指出我无法绑定新套接字。
就我而言,套接字被识别为 具有本地 IP 的本地端口和具有远程 IP 和协议的远程端口。因此,如果两个套接字在这 4 个套接字中的一个不同,则可以将它们作为单独的连接处理。
然而,我仍然遇到异常。
如何对多个客户端进行 TCP 打孔?根据 this 维基百科页面,如果发件人不绑定套接字,它应该可以工作。
这是我的自定义 NetClient
class 中 Connect()
方法的代码。 (它包含一个 TcpClient
并表示与远程端点的连接。)
private async Task<bool> Connect(string _ip)
{
IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, port);
tcpClient = new TcpClient(_endPoint);
int tick = timeOut;
while (tick >= 0)
{
try { await tcpClient?.ConnectAsync(_ip, port); }
catch { }
if (tcpClient.Connected) return true;
tick--;
await Task.Delay(1000);
}
return false;
}
仍然没有运气。有人可以帮忙吗?
好的,我找到了解决办法!对于那些可能遇到同样问题的人,显然有一个选项可以告诉 TCP 套接字本地端点 可以重用 .
根据 OS 和 TCP 实现,您可以为套接字添加选项 SO_REUSEADDRESS
和 SO_REUSEPORT
。这将使套接字忽略端点重复。 (就我而言,它仅适用于本地端点。)
访问 this 网站以获取有关该主题的更多信息,这是一本非常好的读物。
现在,您需要在绑定套接字之前设置这些属性。因此,您需要从 TcpClient 构造函数中单独调用 socket.Bind()
。
使用TcpClient.Client
访问tcpClient的socket。
创建具有可重用本地端点的 TcpClient 的正确方法:
TcpClient client = new TcpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(new IPEndPoint(IPAddress.Any, port));
完成这些步骤后,您应该不会遇到任何套接字绑定问题。希望对您有所帮助!
我正在开发一个点对点文件共享应用程序,无需中央服务器即可用于传输文件。
在一对一文件传输方面,它就像一个魅力,但我最初计划的方式是,发件人可以将文件发送给多个客户端。
该应用程序使用 TCP 打孔,因此不需要端口转发。问题是,为了使 TCP 打洞工作,我需要为每个 TCPClient 指定一个本地端口。因此,我需要绑定套接字。
TCPClient client = new TCPClient(port);
问题是,在创建新客户端时(建立连接后),我会收到错误消息,指出我无法绑定新套接字。
就我而言,套接字被识别为 具有本地 IP 的本地端口和具有远程 IP 和协议的远程端口。因此,如果两个套接字在这 4 个套接字中的一个不同,则可以将它们作为单独的连接处理。
然而,我仍然遇到异常。
如何对多个客户端进行 TCP 打孔?根据 this 维基百科页面,如果发件人不绑定套接字,它应该可以工作。
这是我的自定义 NetClient
class 中 Connect()
方法的代码。 (它包含一个 TcpClient
并表示与远程端点的连接。)
private async Task<bool> Connect(string _ip)
{
IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, port);
tcpClient = new TcpClient(_endPoint);
int tick = timeOut;
while (tick >= 0)
{
try { await tcpClient?.ConnectAsync(_ip, port); }
catch { }
if (tcpClient.Connected) return true;
tick--;
await Task.Delay(1000);
}
return false;
}
仍然没有运气。有人可以帮忙吗?
好的,我找到了解决办法!对于那些可能遇到同样问题的人,显然有一个选项可以告诉 TCP 套接字本地端点 可以重用 .
根据 OS 和 TCP 实现,您可以为套接字添加选项 SO_REUSEADDRESS
和 SO_REUSEPORT
。这将使套接字忽略端点重复。 (就我而言,它仅适用于本地端点。)
访问 this 网站以获取有关该主题的更多信息,这是一本非常好的读物。
现在,您需要在绑定套接字之前设置这些属性。因此,您需要从 TcpClient 构造函数中单独调用 socket.Bind()
。
使用TcpClient.Client
访问tcpClient的socket。
创建具有可重用本地端点的 TcpClient 的正确方法:
TcpClient client = new TcpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(new IPEndPoint(IPAddress.Any, port));
完成这些步骤后,您应该不会遇到任何套接字绑定问题。希望对您有所帮助!