一日一点RakNet(44)--NAT Type detection
来源:互联网 发布:泰国 知乎 编辑:程序博客网 时间:2024/05/16 11:17
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中的例子。
By北洋小郭
转载请注明出处,请勿用于商业用途,谢谢!
- 一日一点RakNet(44)--NAT Type detection
- RakNet学习(43) -- NAT Type detection
- 一日一点RakNet(25)--NAT traversal architecture
- 一日一点RakNet(45)--NAT punchthrough
- 一日一点RakNet(1)--RakNet
- 一日一点RakNet(1)--RakNet
- 一日一点RakNet(0) -- 开篇
- 一日一点RakNet(3)--介绍
- 一日一点RakNet(10)--Startup
- 一日一点RakNet(11)--Connecting
- 一日一点RakNet(15)--SystemAddress
- 一日一点RakNet(16)--BitStream
- 一日一点RakNet(20)--NetworkIDObject
- 一日一点RakNet(21)--Statistics
- 一日一点RakNet(31)--Autopatcher
- 一日一点RakNet(36)--FileListTransfer
- 一日一点RakNet(41)--Lobby2Client_360
- 一日一点RakNet(47)--RakVoice
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器
- S3C2440中断解析和基于WINCE操作系统的中断分析(整理于网络,用于按键中断使用)
- WebKit的智能指针分析 - Part 1:RefCounted
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第七篇:闲话ASP.NET MVC
- android 系统定制的小技巧(网络收集)
- 一日一点RakNet(44)--NAT Type detection
- iPHone限定设备。
- shell-init: error retrieving current directory
- Write buffer的作用
- cluster_interconnec
- android 修改谷歌拼音输入法全屏时的高度
- C语言中函数参数的入栈顺序
- mark
- 一步步学Linux网络编程--ping命令的实现分析