我已经看过并阅读了很多类似的问题,以及相应的维基百科文章(NAT traversal,STUN,TURN,TCP hole punching),但压倒性的数量信息并没有真正帮助我解决我的一个非常简单的问题:
我正在编写一个P2P应用程序,我希望NAT后面的两个应用程序用户能够相互连接。连接必须可靠(与TCP的可靠性相当),所以我不能只切换到UDP。该解决方案应该适用于当今的通用系统而无需重新配置。如果有帮助,解决方案可能涉及可连接的第三方,只要它不必代理整个数据(例如,获取对等方的外部(WAN)IP地址)。
据我所知,我唯一的选择是使用“可靠的UDP”库+ UDP hole punching。这有(C / C ++)库吗?我在enet中找到related question,但它只处理解决方案的前半部分。
还有别的吗?我看过的事情:
答案 0 :(得分:6)
ICE收集要连接的候选IP /端口目标列表。每个对等体收集这些,然后每个对象按顺序对每个候选者进行连接检查,直到检查通过或检查失败。
当Alice试图连接到Bob时,她会以某种方式获取可能的方式列表 - 由Bob决定 - 她可以连接到Bob。 ICE称这些候选人。 Bob可能会说,例如:“我的本地套接字192.168.1.1:1024/udp,我的外部NAT绑定(通过STUN找到)是196.25.1.1:4454/udp,你可以在1.2调用媒体中继(中间盒) .3.4:6675 / UDP”。 Bob将其放入SDP数据包(这些不同候选者的描述)中,并以某种方式将其发送给Alice。 (在SIP中,ICE的原始用例,SIP INVITE / 200 / ACK交换中携带的SDP,设置SIP会话。)
ICE是可插拔的,您可以配置候选人的确切性质/数量。您可以尝试直接链接,然后向STUN服务器请求绑定(这会在您的NAT中打出一个洞,并告诉您该洞的外部IP /端口,您将其放入会话描述中),并且要求TURN服务器转发您的数据。
ICE的一个缺点是你的同伴交换了你可能会或可能不喜欢的SDP描述。另一个是TCP支持仍在draft form,这对您来说可能是也可能不是问题。 [更新:ICE现已正式RFC 6544。]
游戏经常使用UDP,因为旧数据无用。 (这就是RTP通常在UDP上运行的原因。)一些P2P应用程序经常使用中间盒或中间盒网络。
IRC使用中间盒网络:IRC服务器构成网络,客户端连接到近端服务器。从一个客户端到另一个客户端的消息可以通过服务器网络传播。
如果做不到这一点,您可以查看BitTorrent的架构并了解它们如何处理NAT问题。正如CodeShadow在下面的评论中指出的那样,BitTorrent依赖于网络中可达的对等体:从某种意义上说,一些对等体形成了一个中间盒网络。如果这些中间盒可以充当中继器,那么你就拥有了类似IRC的架构,但是它是动态设置的。
答案 1 :(得分:3)
我推荐libjingle,因为它主要依赖于P2P网络通信的一些主要视频游戏公司使用它。 (您是否听说过Steam?Vavle也使用libjingle,请参阅页面中的“点对点网络”会话:https://partner.steamgames.com/documentation/api)
但是,始终工作解决方案将使用中继服务器。由于没有“标准”方式通过NAT,因此如果必须始终在任何对等方之间建立连接,则应将此中继服务器选项作为后备策略。