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_REUSEADDRESSSO_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));

完成这些步骤后,您应该不会遇到任何套接字绑定问题。希望对您有所帮助!