有人能给出一个UDP打洞的例子吗?
实际上,我想写一个聊天程序,让人们在知道对方IP地址的情况下进行聊天。但是两台机器都在防火墙路由器后面。因此,我需要打洞以便进行通信。
我想要一个函数,调用该函数后将会打洞,并且未来的通信将可以轻松进行——如果这不算太过分的话 :)
有人能给出一个UDP打洞的例子吗?
实际上,我想写一个聊天程序,让人们在知道对方IP地址的情况下进行聊天。但是两台机器都在防火墙路由器后面。因此,我需要打洞以便进行通信。
我想要一个函数,调用该函数后将会打洞,并且未来的通信将可以轻松进行——如果这不算太过分的话 :)
简短回答:无法可靠地完成。
长篇回答:
“打洞”指的是触发路由器的自动NAT规则以允许入站流量。当您发送UDP数据包时,路由器(通常)会创建一个临时规则,将您的源地址和端口映射到目标地址和端口,反之亦然。只有来自目标地址和端口(而没有其他地址和端口)的UDP数据包才会通过并传递回原始的源地址和端口(而没有其他地址和端口)。该规则将在几分钟内超时,如果没有活动则会被清除。
当两个端点都在NAT或防火墙后面时,要使其正常工作需要同时让双方向对方发送数据包。这意味着双方都需要知道对方的公共 IP地址和端口号,并且需要通过其他方式进行通信。
如果程序位于NAT后面,则无法直接确定其自己的公共IP地址(它只能看到其私有地址,如192.168.x.x
)。但是,由于您假设涉及的人都知道对方的IP地址,因此这些人可以直接输入对方的地址。
但是真正的问题在于,程序也无法直接确定路由器在公共端口上使用的端口号。您的程序可能绑定到本地机器上的12345端口,但路由器可以将其映射到公共一侧的任何端口。(想象一下局域网中有两台计算机都从端口12345发送数据包,显然路由器必须将其中一台映射到不同的数字。)因此,即使您和对方知道绑定的本地端口号,也无法知道路由器向外界显示的端口号是多少。
Lidgren网络库内置了此功能。将库添加到应用程序后,您将实例化一个NetServer,并连接两个NetClients,然后调用NetServer.Introduce()。
链接到Lidgren: https://github.com/lidgren/lidgren-network-gen3