首页 文章

需要帮助设置udp打孔以进行p2p数据传输 . 无法让STUN工作

提问于
浏览
0

我正在尝试将UDP数据包从一个客户端发送到另一个客户端 . 设 C1 是我用来接收数据的客户端和 C2 将发送数据的客户端 . 我在做什么:

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

  • 我通知每个客户其他人的IP地址和公共端口 .

  • C1 在其公共地址和端口上发送数据包到 C2 并开始侦听数据包 . 同时 C2 开始发送包含我想要传输的数据的数据包 .

C1 只是在收到永远不会到达的数据包时挂起 . 我在做UDP漏洞错误吗?

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

UPDATE:

我现在知道我的路由器允许发夹 . 我向我的路由器上的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");
            }
        }
    }

UPDATE 2:

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

感谢大家的帮助 .

2 回答

  • 1

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

    此外,如果C1和C2位于同一子网上,那么您的NAT可能不允许发夹 . “发夹”是通过外部地址在内部发送的能力 . 并非所有NAT都支持此功能 . 准备尝试连接内部候选地址以及STUN发现的外部地址 .

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

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

  • 0

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

    如果C1和C2在不同的网络中 . 然后,如果C2将数据包发送到C1s公共IP:端口,那么C2的NAT将为C1的公共IP:端口创建映射 . 之后,C2的公共IP:端口中的C1的任何数据都将被转发到C2 .

    但我认为在您的方案中,数据包不会离开NAT,因为它们都在同一网络下 . 这就是为什么NAT没有创建任何映射 . 所以你的打孔失败了 .

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

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

    编辑:

    如果两个客户端的NAT组合类似于Symmetric vs Symmetric,则孔冲孔将不起作用 . 所以首先检查两端的NAT类型是什么 .

    不要用数据包向另一端发送垃圾邮件以打孔 . 如果您使用数据包泛洪,NAT可以阻止您的IP . 从一侧打孔并且TTL值低 . 因此用于打孔的数据包离开NAT但不到达其他NAT . 这样就可以成功地进行打孔,而其他的侧面NAT也不会被淹没 . 从另一侧尝试稍晚发送数据包,以便从另一侧完成打孔 . 当打孔侧接收到第一个数据包然后停止打孔并开始正常发送数据包 .

相关问题