需要帮助设置udp穿孔p2p数据传输.不能让STUN工作

本文关键字:不能 数据传输 STUN 工作 p2p 穿孔 帮助 设置 udp | 更新日期: 2023-09-27 18:10:44

我正在尝试从一个客户端向另一个客户端发送UDP数据包。让C1是我用来接收数据的客户端,C2是发送数据的客户端。我在做什么:

  1. 向STUN服务器询问两个客户端的公网IP地址和端口

  2. 我通知每个客户端对方的IP地址和公共端口。

  3. C1通过其公共地址和端口向C2发送数据包,并开始侦听数据包。同时,C2开始发送包含我想要传输的数据的数据包。

C1只是挂起接收一个从未到达的数据包。我做UDP洞打孔错误吗?

我在同一网络上的同一台计算机上对两个客户端进行测试,但服务器在另一个具有公共IP的网络上的服务器上。我想说的是,两个客户端的公共地址是相同的,而我正在测试,这是一个问题吗?

更新:

我现在知道我的路由器允许发夹。我转发了路由器上的UDP端口,使用公共IP地址,我可以从一个客户端向另一个客户端发送数据包。

这是我用来测试是否可以在c#中打孔的代码:

static UdpClient udpClient = new UdpClient(30001);
static IPAddress remoteIp;
static int remotePort;
static void Main(string[] args)
{
        // Send packet to server so it can find the client's public address and port 
        byte[] queryServer = Encoding.UTF8.GetBytes("something");
        udpClient.Send(testMsg, testMsg.Length, new IPEndPoint(IPAddress.Parse("199.254.173.154"), 30000));
        // Wait for a response from the server with the other client's public address and port
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);           
        byte[] dataJsonBytes = udpClient.Receive(ref sender);
        JObject json = JObject.Parse(Encoding.UTF8.GetString(dataJsonBytes));
        remoteIp = IPAddress.Parse(json["IP"].ToString());
        remotePort = Int32.Parse(json["port"].ToString());                                                    
        // Start spamming the other client with packets and waiting for response
        Thread sendingThread = new Thread(sendPacket);
        Thread receivingThread = new Thread(receivePacket);
        sendingThread.Start();
        receivingThread.Start();
        Console.ReadLine();
    }
    private static void sendPacket()
    {
        byte[] udpMessage = Encoding.UTF8.GetBytes("Forcing udp hole punching!!'n");
        while (true)
        {               
            udpClient.Send(udpMessage, udpMessage.Length, new IPEndPoint(remoteIp, remotePort));
            Thread.Sleep(100);
        }
    }
    private static void receivePacket()
    {
        IPEndPoint senderEp = new IPEndPoint(IPAddress.Any, 0);
        udpClient.Client.ReceiveTimeout = 500;
        while (true)
        {
            try
            {
                byte[] receivedData = udpClient.Receive(ref senderEp);
                Console.Write(Encoding.UTF8.GetString(receivedData));
            }
            catch (Exception)
            {
                Console.Write("Timeout!!'n");
            }
        }
    }
更新2:

在@Tahlil的帮助下,我能够弄清楚我用来检查NAT类型的算法是有缺陷的,我试图在对称NAT后面打孔。所以问题是没有注意到我的代码上的错误……我建议对所有面临同样问题的人都确定地断言NAT类型。

谢谢大家的帮助。

需要帮助设置udp穿孔p2p数据传输.不能让STUN工作

C2当然会挂起。因为C2 NAT很可能在C2发送他的数据包之前拒绝了C1发送的原始数据包。在所有这些中构建一些重试逻辑来克服这些问题。

同样,如果C1和C2在同一子网上,那么你的NAT可能不允许发夹。"发夹"是通过外部地址向内部发送的能力。并非所有国家都支持这一点。准备好尝试连接内部候选地址以及STUN发现的外部地址。

无论如何,从我之前给出的答案开始。

https://stackoverflow.com/a/8524609/104458

一些NAT不允许来自未知来源的数据包。这就是为什么我们在NAT中打孔,以便NAT可以识别未知IP并为其创建映射。

如果C1和C2不在同一网络中。然后,如果C2发送一个数据包到C1的公共IP:port,那么C2的NAT将为C1的公共IP:port创建一个映射。之后,C2的公共IP:Port中来自C1的任何数据都将被转发到C2。

但我认为在你的情况下,数据包没有离开NAT,因为它们都在同一个网络下。这就是NAT不创建任何映射的原因。所以你的打孔失败了。

因此,当您从C1向C2的公共IP地址发送数据时,您假设到那时C2已经为C1的地址打了一个孔,NAT已经创建了一个映射。但是由于C1在同一个网络中,C2的打孔失败了。

如果你在同一个网络中,为什么你需要打孔?这是一个奇怪的意图,因为C1和C2可以直接向彼此的私有IP发送数据包并建立连接。C1和C2在不同网络时,需要冲孔。

编辑:

如果两个客户端的NAT组合是对称对对称的,则穿孔将不起作用。首先检查两端的NAT类型是什么。

不要为了打洞而向另一端发送垃圾邮件。NAT可以阻止你的IP,如果你的数据包泛滥。单侧打孔,TTL值低。这样,打算打洞的数据包离开NAT,但没有到达另一个NAT。这样打洞将成功完成,另一方NAT不会被淹没。从另一边尝试发送数据包晚一点,这样打孔完成从另一边。当穿孔方收到第一个数据包时,停止穿孔并开始正常发送数据包。