内网电脑用UDP进行通信,原理请看。。。。谁能实现一下呢???请大家讨论。(300分)

  • 主题发起人 主题发起人 kkkchenA
  • 开始时间 开始时间
K

kkkchenA

Unregistered / Unconfirmed
GUEST, unregistred user!
3.3 UDP hole punching
第三种技术,也是这篇文章的一个重要点之一,就是被称为"UDP Hole Punching"的技术。当两个需要通讯的主机可能都在middlebox后面的时候,UDP hole punching依赖于cone NAT和普通防火墙的一些特性,允许合适的P2P应用程序以"punch holes"方式通过middlebox并且建立彼此之间直接的连接。这种技术在RFC 3027[NAT- PORT]的5.1节中简要的提及,并且在英特网[KEGEL]非证实的提到,也在最近的一些协议[TEREDO, ICE]中用到。正如名字中的所提到的,这种技术只能用于UDP连接。

我们将会考虑两个特别情况,并且考虑应用程序如何完善的处理两者之间的握手连接。第一种情况下,也是较为普通的情况,两个在不通的NAT后面的客户端要求直接的进行P2P连接。第二种情况,两台客户端位于同一个NAT后面,但不能肯定(两台客户端位于同一个NAT后面)。

3.3.1 位于不同NAT后面(Peers behind different NATs)
假设客户端A和B都有自己的私有IP地址,也都位于不同的NAT后面。P2P应用程序在A、B和服务器S上运行,用的都是UDP端口1234。A和B各自和服务器S建立UDP通讯连接,使NAT A为A的连接分配一个自己的公共端口62000,而NAT B为B的连接分配的是31000端口。

Server S
18.181.0.31:1234
|
|
+----------------------+----------------------+
| |
NAT A NAT B
155.99.25.11:62000 138.76.29.7:31000
| |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234

现在推想一下,客户端A想要直接和B建立一个UDP通讯会话。假设A简单的发一个UDP信息包到B的公共地址138.76.29.7:31000,然而NAT B将会丢弃这些进入的数据信息(除非它是一个FULL cone NAT),原因是NAT B和S已经建立的外部会话,而A发送的信息中的源地址和端口号是和S不匹配的(可以参照一下上面的内容,匹配才能接受)。同样,假如B发送一个条UDP数据包给A的公网地址,NAT A也会丢弃。

但是,假设A发出一个UDP数据信息给B的公网IP地址,同时也通过服务器S传递一个请求给B,要求B也发一个UDP信息给A的公网IP地址。A直接向B的公共IP地址(138.76.29.7:31000)发送的数据包会让NAT A在A的私有地址和B的公网地址之间建立了一个新的连接会话。同时,B到A的公网地址(155.99.25.11:62000)的信息会导致NAT B在B的私有地址和A的公共地址之间建立一个新的连接会话。一旦这种新的UDP连接在两者之间建立起来,客户端A和B就不需要服务器S的"介绍"就能彼此直接通讯了。

UDP hole punching技术有几个很有用的特点。一旦在两个位于middlebox后面的客户端建立了一个直接的P2P连接,在连接中的任何一方都可以扮演一个"介绍人"的角色,依次继续和另一个客户端建立连接,减少了最初的服务器S的负担。如果说有[STUN]的话,假如两个中的任意一个或两个都碰巧不在middlebox后面,上述应用程序将同样可以建立P2P通讯通道,应用程序不需要尝试明确middlebox的类型。Hole punching技术甚至可以自动的运用在多级NAT下面,多重NAT就是那些客户端需要经历多级地址转换才能进入公网。

3.3.2 位于同一NAT后(Peers behind the same NAT)
现在考虑两台客户端(但并不确定)都在同一个NAT后面的情况,因此会有私有IP地址空间。客户端A与服务器S建立一个UDP会话,NAT会分配一个公共端口62000。客户端B与服务器S也建立一个简单的连接,NAT为此分配一个公共端口62001。

Server S
18.181.0.31:1234
|
|
NAT
A-S 155.99.25.11:62000
B-S 155.99.25.11:62001
|
+----------------------+----------------------+
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234

假想A和B使用UDP hole punching技术与服务器S的建立一个外部的通讯路线做为中间介绍。然后A和B将可以通过服务器S得到各自公共IP地址和端口号,然后使用这些地址各自向对方发送数据。两个客户能够以这种方式彼此通讯,只要NAT不仅仅允许外网上的主机可以和内网上的主机进行UDP传输会话,也可以允许内网上的主机可以和其他内网的主机进行UDP会话。我们在"loopback translation"中设计到这种情况,因为来自私有网络的数据包到达NAT后,会"looped back"到私有网络上就象从公网来的一样。例如,当A向B的公共IP地址发送一个UDP包,这个包的包头有一个源IP地址和端口,是10.0.0.1:1234,而目的地址是155.99.25.11.62001。NAT接受到这个包,会把源地址转换(映射)为155.99.25.11:62000(就是A的公网地址),把目的地址转换为10.1.1.3:1234,然后发给B。即使NAT支持回环映射,NAT的转换和发送步骤看上去是多余的,在A和B通讯时似乎为NAT添加了潜在的负担。

这个问题的解决方法是直接的。当A和B一开始在服务器S上交换地址信息时,它们就可以包含他们自己的IP地址和端口号,并且是可见的,对服务器S也是可见的。客户端根据它们得到的地址同时开始向对方发数据包,并建立成功的通讯。假如这两个客户端都在同一NAT后面,数据包象通讯一开始就能直接到达,而不需要通过NAT就能建立直接连接。假如这两个客户端位于不同的NAT后,到达彼此私有地址的数据包会被丢弃,但是客户端可以通过各自的公共地址来建立连接。重要的是这些数据包需要通过一些方法去鉴别,然而,在这种情况下,A发到B的私有地址的数据包完全有可能到达A私网内其他无关的终端,B发到A的包也是这样。
 
希望有这方面经验的朋友进来说一下,例如那个端口可以存在多久,建立连接以后可以保持多久,怎么保证辅助服务器的信息跟通信机器的信息同时到达.............
 
上面那么长的一段话,需要用代码实现的部分只有一段:

假设A发出一个UDP数据信息给B的公网IP地址,同时也通过服务器S传递一个请求给B,要求B也发一个UDP信息给A的公网IP地址。A直接向B的公共IP地址(138.76.29.7:31000)发送的数据包会让NAT A在A的私有地址和B的公网地址之间建立了一个新的连接会话。同时,B到A的公网地址(155.99.25.11:62000)的信息会导致NAT B在B的私有地址和A的公共地址之间建立一个新的连接会话。一旦这种新的UDP连接在两者之间建立起来,客户端A和B就不需要服务器S的"介绍"就能彼此直接通讯了。
 
楼主有没有进行测试呢,我以前也想过这个方法,
但没有条件测试
 
我也没有条件去测试啊,所以发贴上来问问做过这样事情的朋友。
不过好像都没有人回帖。
 
>>例如那个端口可以存在多久
跟具体的middlebox有关系,这里的middlebox可能是防火墙等设备,有些设备是30分钟。原英文文档好像有说到这方面的内容(nat的那一段)。
>>建立连接以后可以保持多久
问题跟上面是一样的
>>怎么保证辅助服务器的信息跟通信机器的信息同时到达.............
Client A 的登录:
Client A 向Server S登记自己的公网IP及端口
Server S 向Client A 发送Client A 所有已上线的好友的公网IP及端口
Server S 向Client A 已上线的好友发送Client A 的公网IP及端口

Client B 的登录:
Client B 向Server S登记自己的公网IP及端口
Server S 向Client B 发送Client B 所有已上线的好友的公网IP及端口
Server S 向需与Client B 已上线的好友发送Client B 的公网IP及端口

现在Client A和Client B都已经知道对方的公网IP和端口了
现假设Client A发起与Client B通讯
Client A要求Server S向Client B发出Client A需要跟它(Client B)通讯的通知

(第一次连接测试:连接失败)
Client A向Client B发出连接包 导致NAT A记录了Client B信息
Client B向Client A发出连接包 导致NAT B记录了Client A信息

(第二次连接测试:)
Client A向Client B发出连接包此时NAT B已经记录了Client A信息,连接成功
Client B向Client A发出连接包此时NAT A已经记录了Client B信息,连接成功

接下来就可以正常通讯了。
在我们的网络环境中测试通过,我们测试的时候是手工连接的。A、B向server s登记,在A程序上输入B的IP和端口,B程序也相同操作,然后A、B程序点击连接。
 
我测试过,A和B就是不通。这段文字我以前也看了,AB都是通过Sygate上网,我按照该文的提示写代码,AB均可以和S互相通信,AB也可以通过S转发消息,但就是实现不了AB的直接通信,郁闷中。。。请实验成功的朋友给大家讲解一下啊,谢谢!
 
觉得 999roseto347,的方法是可行的,
只是需要进行多次连接测试,来欺骗NAT转换

我想 999roseto347 应该是测试通过了的,
我也只是测试到第一次连接测试,后面的就没有试过,
但我觉得,第二次甚至第三次连接测试才是最关键的
 
谢谢 999roseto347 hardware007 lich shinyv 来参加讨论。
在这里分数就给 999roseto347 加上。
 
shinyv你可能理解错了。
>>AB都是通过Sygate上网
Sygate是代理软件。这篇文章里说的middlebox是指防火墙、路由器等设备。
如果你想通过代理软件进行连接你可以通过sockets4、5连接

lich:我同事测的,在两台路由器两个公网IP的环境下。
 
端口在NAT设备上的保持时间大概为1分钟
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部