C#实现 P2P 之 U DP 穿透 NAT 的原理 分类: 网络2011-11-05 13:33 838 人阅读 评论(1) 收藏 举报 p2pc#bufferserversessionuser 论坛上经常有对P2P 原理的讨论,但是讨论归讨论,很少有实质的东西产生(源代码)。呵呵,在这里我就用自己实现的一个源代码来说明 UDP 穿越 NAT 的原理。 首先先介绍一些基本概念: NAT(Network Address Translators),网络地址转换:网络地址转换是在 IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用。NAT 分为两大类,基本的NAT 和 NAPT(Network Address/Port Translator)。 最开始 NAT 是运行在路由器上的一个功能模块。 最先提出的是基本的NAT,它的产生基于如下事实:一个私有网络(域)中的节点中只有很少的节点需要与外网连接(呵呵,这是在上世纪 90 年代中期提出的)。那么这个子网中其实只有少数的节点需要全球唯一的IP 地址,其他的节点的IP 地址应该是可以重用的。 因此,基本的NAT 实现的功能很简单,在子网内使用一个保留的IP 子网段,这些 IP 对外是不可见的。子网内只有少数一些 IP 地址可以对应到真正全球唯一的 IP 地址。如果这些节点需要访问外部网络,那么基本 NAT 就负责将这个节点的子网内 IP 转化为一个全球唯一的IP 然后发送出去。(基本的NAT 会改变 IP 包中的原IP 地址,但是不会改变 IP 包中的端口) 关于基本的NAT 可以参看 RFC 1631 另外一种 NAT 叫做 NAPT,从名称上我们也可以看得出,NAPT 不但会改变经过这个 NAT 设备的IP 数据报的IP地址,还会改变 IP数据报的TCP/UDP端口。基本 NAT 的设备可能我们见的不多(呵呵,我没有见到过),NAPT 才是我们真正讨论的主角。看下图: Server S1 18.181.0.31:1235 | ^ Session 1 (A-S1) ^ | | 18.181.0.31:1235 | | v 155.99.25.11:62000 v | | NAT 155.99.25.11 | ^ Session 1 (A-S1) ^ | | 18.181.0.31:1235 | | v 10.0.0.1:1234 v | | Client A 10.0.0.1:1234 有一个私有网络10.*.*.*,Client A 是其中的一台计算机,这个网络的网关(一个NAT 设备)的外网IP 是155.99.25.11(应该还有一个内网的IP 地址,比如 10.0.0.10)。如果 Client A 中的某个进程(这个进程创建了一个UDP Socket,这个Socket 绑定 1234 端口)想访问外网主机18.181.0.31 的1235端口,那么当数据包通过 NAT 时会...