UDP穿透帮助

4
我想向我的游戏添加基于Peer to Peer的网络连接,包括互联网。我已经实现了仅限于 LAN 的版本,使用.NET的点对点类在本地网络内部进行连接。
我意识到需要使用UDP洞穴技术才能与防火墙后面的其他客户端建立连接。
这是我开始实现它的方式: 服务器是一个HTTP服务器,使用非常简单的PHP脚本完成工作。
1. 在服务器上注册名称,并将私有IP地址和端口作为GET变量发送。 2. 当服务器收到注册请求时,它将保存公共端点和私有端点。 3. 请求连接到另一个客户端。 4. 服务器将返回客户端的私有和公共端点。 5. 每隔两秒钟,第二个客户端将向服务器检查一次,并且如果有另一个客户端试图连接它,它也会得到该客户端的端点。 6. 两个客户端开始不断发送彼此的公共端点,直到他们得到有效响应。
现在我有一些问题:
1. 服务器可以是HTTP服务器吗? 2. 当我向HTTP服务器发出请求时,每次请求时客户端端口都会改变。是否总是将私有端点与同一公共端点匹配? 3. 请求服务器必须具有与发送到客户端的UDP消息相同的源端点吗? 4. 是否有一种方法可以使用指定的源端点在C#中连接到HTTP服务器? 5. 是否存在问题在我的实现中?
谢谢!

.NET的点对点类是什么? - Predator
System.net.P2P 命名空间 - 适用于本地连接,非常好用。 - user434565
1
我曾经尝试过这个解决方案,并且取得了一些成功,但不幸的是回答的时间不太好。如果明天仍未解决,我将尝试提出我的观点。 - Independent
2个回答

3
UDP打洞是一个复杂的话题,已经有很多尝试找到可行的解决方案。问题在于有很多不同类型的NAT路由器,而且没有标准的NAT实现方式,所以所有的路由器表现都有所不同。
一些尝试已经被标准化,例如 STUNICE。它们仍然只适用于大多数情况,并且积累了很多知识并解决了许多问题,这比你的尝试要好得多,因为你无法测试每个NAT路由器的解决方案。例如,Skype花费了多年时间完善其NAT遍历机制。
我建议您查看STUN或更好地查看ICE。尝试实现其中之一或寻找现有的实现。
另一个选择可能是在路由器上创建端口转发,例如使用UPnPNAT-PMP
说实话,如果.NET点对点类带有NAT穿透机制,我也不会感到惊讶,但我对它们不熟悉。

谢谢!当我将服务器通信方式从HTTP改为UDP时,它就像魔法般地运行了! - user434565

0

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 及更高版本 (.net4.0 <) 遍历 NAT。有一个方法 AllowNATTraversal(bool value),将值设置为 true 以进行 NAT 遍历。它使用 IPv6 地址进行连接。您可以通过在命令提示符中编写一些命令从 "Teredo" 服务器获取 IPv6 全局地址。实际上,IPv6 是用于避免这个问题的技术。


当涉及到IP或端口的数据包丢失时,应该如何处理? - user1914692
在UDP中,没有任何方法可以获取有关数据包的确认。因此,在传输过程中可能会丢失数据包。如果您需要有关数据包传递的任何确认,则无法对此进行任何处理,最好使用TCP。它具有有关数据包的机制来生成确认。但是,由于它具有一些先进的流量控制机制,因此速度比UDP慢。 - Sandaru
1
对于媒体流,由于网络繁忙而导致帧被丢弃是可以接受的(实际上经常被采用)。然而,对于打洞所需的信息,我们需要这些信息,否则后续的过程无法进行。因此,您认为我们可以先使用TCP来检索打洞所需的信息,然后再使用UDP来进行媒体流吗? - user1914692

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接