RakNet学习(43) -- NAT Type detection
来源:互联网 发布:淘宝旺铺多少钱一个月 编辑:程序博客网 时间:2024/06/05 04:38
NAT类型检测
要完成NAT穿透需要提前确定NAT类型
NAT穿透的成功几率依赖于NAT使用的算法类型。
Full cone NAT:可以从先前使用过的端口上接收到任何数据报。可以从远端的Peer接收到第一个数据报。
Address-Restricted cone NAT:只要数据报源IP地址是先前我们发送过数据的系统,那么可以从端口上收到数据。如果两个系统同时发送数据报,可以接收到第一个数据报。否则,在我们发送一个数据报以后才会收到第一个数据报。
Port-Restricted cone NAT:与Address-restricted cone NAT类似,但是我们需要发送到正确的远端IP和正确的远端端口。到不同目的地的相同的源地址和端口使用相同的映射。
Symmetric NAT: 为每一远端目的地选择同的端口。到不同目的地的相同的源地址和端口使用不同的映射。因为端口号不同,第一次的外部穿透尝试就会失败。如果要使得这种模式工作,它要求有端口预测(MAX_PREICTIVE_PORT_RANGE > 1),以及路由按序选择端口。
Success Graph
Router Type
Full cone NAT
Address-Restricted cone NAT
Port-Restricted cone NAT
Symmetric NAT
Full cone NAT
YES
YES
YES
YES
Address-Restricted cone NAT
YES
YES
YES
YES
Port-Restricted cone NAT
YES
YES
YES
NO
Symmetric NAT
YES
YES
NO
NO
NatTypeDetection插件允许你检测你自己的NAT的类型,以及NAT穿透是否可以完成。这个要在加入游戏之前确定。
NAT 类型检测算法
1. 客户端在相同的IP地址打开两个端口。在NatTypeDetectionClient中,RakNet的socket是第一个端口,c2是第二个端口的socket,这两个socket在NatTypeDetection::DetectNATType()中创建。
2. 服务器在同一个IP地址上打开两个端口,以及在三个其他的IP地址上打开一个端口。这个在NatTypeDetectionServer::Startup()函数中完成。第一个IP地址上的第一个端口是正常的RakNet端口。第一个IP地址上的第二个端口是s1p2。其他的三个地址绑定到s2p3, s3p4和s4p5。
3. 客户端连接到服务器通常是在第一个Ip地址上实现。
4. 客户端请求NAT类型检测开始。
5. 服务器尝试向客户端的第二个端口发送数据。这个端口是前面没有打开过的端口,因此如果接收到了,那么客户端就没有位于NAT之后。这个动作可以再NatTypeDetectionServer::Update()方法中实现,通过STATE_TESTING_NONE_1和STATE_TESTING_NONE_2来定义。两次尝试的原因是每一次尝试出现两次。每一次尝试的时间是ping * 3 + 50毫秒。S4P5用在这里。
6. 服务器从不同的IP地址向客户端的不同端口发送数据,这个端口RakNet已经连接。如果接收到了数据,那么客户端可以从已经使用的端口上接收到任何源IP地址的数据报。这个情况通常是full-cone NAT。s2p3用于这个目的。
7. 在已经连接的Ip地址上从第二个端口发送数据,s102。如果接收到了数据,那么客户端的NAT类型是address-restriced cone NAT。
8. 客户端向服务器的另外一个IP地址发送数据,从第一个端口(已经连接)。如果IP地址和端口是相同的,那么客户端使用external IP地址和端口来处理来自相同源地址的所有连接。这个是port-restriced NAT类型。
9. 其他的都是symmetric NAT
客户端实现:
1. 创建一个插件实例:NatTypeDetectionServer nayTypeDetectionClient。
2. 将插件附加到RakPeerIntance实例上:rakPeer->AttachPlugin( &nayTypeDetectionClient);
3. 连接服务器,等待ID_CONNECTION_REQUEST_ACCEPTED消息。使用如下的代码来使用RakNet提供的免费服务器:rakPeer->(“8.17.250.34”, 60481, 0, 0);
4. 使用服务器的SystemAddress调用DetectNATType。
5. 等待ID_NAT_TYPE_DETECTION_RESULT消息
6. 第一个字节包含了你的NAT类型。参考NATTypeDetectionCommon.h的NATTypeDetectionResult枚举类型。
7. 为这个枚举类型提供了各种功能函数:CanConnect(), NATTypeDetectionResultToString(), NATTypeDetectionResultToStringFriendly()。
服务器实现:
1. 在某地设置一台主机,不要使用NAT/或者位于防火墙之后。(RakNet提供了一个免费的服务器,地址为8.17.250.34:60481,但是为了使用方便,你可能想要维护你自己的主机,以便长时间运行)。服务器必须有足够多的外部IP地址,正如在NAT Type Detection Algorithm中所描述的那样。
2. 创建一个插件实例:NatTypeDetectionServer natTypeDetectionServer。
3. 将插件附加到RakPeerInterface实例上:rakPeer->AttachPlugin( &natTypeDetectionServer);
4. 获得系统上的IP地址列表:
char ipList[ MAXIMUM_NUMBER_OF_INTERNAL_IDS ][ 16 ];
unsigned int binaryAddresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS];
SocketLayer::Instance()->GetMyIP( ipList, binaryAddresses );
5. 调用natTypeDetectionServer.Startup( ip2, ip3, ip4);
ip2, ip3, ip4必须是没有使用的IP地址。如果你调用RakPeer::Startup()方法中将RakNet绑定到ip1,然后使用2nd到4th到ipList中。
例子:
参考\Samples\NATCompleteClient中的例子。
- RakNet学习(43) -- NAT Type detection
- 一日一点RakNet(44)--NAT Type detection
- RakNet学习(44) -- NAT punchthrough
- RakNet学习(24) -- NAT traversal architecture
- RakNet学习(1)--RakNet
- RakNet学习
- 一日一点RakNet(25)--NAT traversal architecture
- 一日一点RakNet(45)--NAT punchthrough
- RakNet学习(3) -- 介绍
- RakNet学习 (9) -- Startup
- RakNet学习(10) -- Connecting
- RakNet学习(14) -- SystemAddress
- RakNet学习(19) -- NetworkIDObject
- RakNet学习(20) -- Statistics
- RakNet(30)学习 -- Autopatcher
- RakNet学习(35) -- FileListTransfer
- RakNet学习(40) -- Lobby2Client_360
- RakNet学习(46) -- RakVoice
- 编程艺术java实现
- android 的tablelayout
- 【转】母函数详解 + HDU习题
- 当页面内容溢出或超出边界时显示省略号
- 常用正则表达式
- RakNet学习(43) -- NAT Type detection
- RakNet学习(44) -- NAT punchthrough
- 数论--大整数取模
- RakNet学习(45) -- Packet Logger
- hdu4883(贪心)
- RakNet学习(46) -- RakVoice
- poj 1231 The Alphabet Game
- 中央台“互联网时代”纪录片分集要点
- 改Eclipse颜色主题