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