【问题标题】:UDP Hole Punching helpUDP打孔帮助
【发布时间】:2011-10-11 06:44:00
【问题描述】:

我正在尝试使用 Peer to Peer 将 Internet 上的网络添加到我的游戏中。 我已经实现了一个仅限 LAN 的版本,它使用 .NET 的点对点类在本地网络中进行连接。

我意识到我需要使用 UDP 打孔来建立与防火墙后面的其他客户端的连接。

这就是我开始实施它的方式: 该服务器是一个 HTTP 服务器,使用非常简单的 PHP 脚本来完成工作。

    • 在服务器上注册名称,将私有 IP 地址和端口作为 GET 变量发送
    • 服务器收到注册请求后,会保存公共端点和私有端点
    • 请求连接到另一个客户端。
    • 服务器将返回客户端的私有和公共端点
    • 每两秒,第二个客户端将与服务器签入,如果有另一个客户端尝试与其连接,它也会获取其端点
    • 两个客户端开始向对方的公共端点发送垃圾邮件,直到获得有效响应

现在我有一堆问题

  1. 服务器可以是 HTTP 服务器吗?
  2. 当我向 HTTP 服务器发出请求时,每次发出请求时客户端端口都会更改。私有端点是否始终与同一个公共端点匹配?
  3. 发往服务器的请求是否必须与发往客户端的 UDP 消息具有相同的源端点?
  4. 有没有办法在 C# 中使用指定的源端点连接到 HTTP 服务器?
  5. 我的实现有什么问题吗?

谢谢!

【问题讨论】:

  • .NET 的点对点类是什么?
  • System.net.P2P 命名空间 - 非常适合本地连接。
  • 我使用了这样的解决方案并取得了一些成功。但不幸的是,答案的时机很糟糕。如果明天还没有解决,我会尽力说明我的观点。

标签: c# .net udp p2p hole-punching


【解决方案1】:

UDP 打洞是一个复杂的话题,并且已经进行了许多尝试以找到可行的解决方案。问题是那里有很多不同的 NAT 路由器,并且没有标准的实现 NAT 的方法,所以所有路由器的行为都有点不同。

一些尝试已经标准化,例如STUNICE。它们仍然只在大多数情况下起作用,而不是全部,但它们积累了很多知识并解决了许多问题——比你的尝试所能做到的还要多,仅仅是因为你无法用阳光下的每一个 NAT 路由器测试你的解决方案.例如,Skype 花了数年时间完善其 NAT 穿越机制。

我建议你看看 STUN 或者最好是 ICE。尝试实现其中之一或寻找现有的实现。

另一种选择可能是简单地在路由器上创建一个端口转发,例如使用 UPnPNAT-PMP

也就是说,如果 .NET 对等类带有 NAT 遍历机制,我不会感到惊讶,但我对它们并不熟悉。

【讨论】:

  • 谢谢!当我将服务器更改为通过 UDP 而不是 HTTP 进行通信时,它就像一个魅力!
【解决方案2】:

STUN 是解决问题的最佳方法。它适用于大多数场景。这是一个简单的示例(C#),它为您提供 NAT 类型、本地 IP:端口和公共 IP:端口。

       try
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(new IPEndPoint(IPAddress.Any, 0));

            STUN_Result result = STUN_Client.Query("stunserver.org", 3478, socket);
            Console.WriteLine("Net Type : " + result.NetType.ToString());
            Console.WriteLine("Local IP : " + socket.LocalEndPoint.ToString());
            if (result.NetType != STUN_NetType.UdpBlocked)
            {
                Console.WriteLine("Public IP : " + result.PublicEndPoint.ToString());
            }
            else
            {
                Console.WriteLine("");
            }
        }
        catch (Exception x)
        {
            Console.WriteLine(x.StackTrace.ToString());
        }

您可以添加一些断点并检查代码的行为。

你也可以使用 vs2010 onwords (.net4.0

【讨论】:

  • IP或端口的数据包丢失如何处理?
  • 在 UDP 中,没有任何方法可以得到关于数据包的确认。因此在转换过程中可能会丢弃数据包。因此,如果您需要有关数据包传递的任何确认,则最好使用 TCP。它具有生成有关数据包的确认的机制。但它比 UDP 慢,因为它有一些先进的流量控制机制。
  • 对于媒体流,由于流量繁忙而丢帧是可以的(实际上通常是首选)。但是,对于打孔的信息,我们需要该信息,否则,后续过程无法进行。那么你认为我们可能首先使用TCP来检索打孔所需的信息吗?之后,我们使用 UDP 流媒体。
猜你喜欢
  • 1970-01-01
  • 2011-06-14
  • 2014-10-17
  • 2019-04-11
  • 2012-11-30
  • 2019-01-13
  • 2011-06-05
  • 2013-01-29
  • 2012-02-26
相关资源
最近更新 更多