`
javascript
  • 浏览: 10892 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论
阅读更多
其实很早我就已经实现了使用TCP协议穿透NAT了,但是苦于一直没有时间,所以没有写出来,现在终于放假有一点空闲,于是写出来共享之。

    一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基本上没有人会告诉你如何使用TCP协议去穿透(甚至有的人会直接告诉你TCP协议是无法实现穿透的)。但是,众所周知的是,UDP是一个无连接的数据报协议,使用它就必须自己维护收发数据包的完整性,这常常会大大增加程序的复杂度,而且一些程序由于某些原因,必须使用TCP协议,这样就常常令一些开发TCP网络程序的人员“谈穿透色变”。那么,使用TCP协议是不是就不能实现穿透呢?答案当然是否定的:TCP协议不仅能实现NAT穿透,而且实现起来比UDP穿透甚至还简单一些。


    要了解如何使用TCP穿透NAT,就要首先看看如何使用UDP穿透NAT。
    我们假设在两个不同的局域网后面分别有2台客户机A和 B,AB所在的局域网都分别通过一个路由器接入互联网。互联网上有一台服务器S。
    现在AB是无法直接和对方发送信息的,AB都不知道对方在互联网上真正的IP和端口, AB所在的局域网的路由器只允许内部向外主动发送的信息通过。对于B直接发送给A的路由器的消息,路由会认为其“不被信任”而直接丢弃。
    要实现 AB直接的通讯,就必须进行以下3步:A首先连接互联网上的服务器S并发送一条消息(对于UDP这种无连接的协议其实直接初始会话发送消息即可),这样S就获取了A在互联网上的实际终端(发送消息的IP和端口号)。接着 B也进行同样的步骤,S就知道了AB在互联网上的终端(这就是“打洞”)。接着S分别告诉A和B对方客户端在互联网上的实际终端,也即S告诉A客户B的会话终端,S告诉B客户A的会话终端。这样,在AB都知道了对方的实际终端之后,就可以直接通过实际终端发送消息了(因为先前双方都向外发送过消息,路由上已经有允许数据进出的消息通道)。


    用UDP来实现以上3步不存在什么理论上的问题,因为UDP是无连接的协议,它允许socket进行“多对一”的通讯(即几个具有不同IP和端口号的socket向一个接收socket发送消息)。但是使用TCP就出现了问题:在一般情况下,TCP socket不允许在已经建立连接的端口上再进行监听和使用该本地端口。换句话说,当AB连接上服务器S后,S将AB的实际终端告诉对方,下一步本该是AB利用对方的实际终端进行直连,但这时你会发现对方的实际终端已经被占用了(就是各自连接到服务器S的会话占用了终端),无法同时listen和 connect。于是很多人得出结论:TCP无法实现NAT穿透。
    于是问题的关键变成了如何复用一个TCP连接的本地终端,这其实不是协议的问题,而是一个API的问题。幸运的是,所有主流操作系统都支持一个特定的TCP套接字选项——SO_REUSEADDR。这个选项允许将多个socket绑定到同一个本地终端。我们建立socket的时候只要加上这么一行:

setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &flag, len) ;   //C++就这么做


_Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)  '这是vb.net 更加简单

    知道上面的知识就很好办了,下面我来说说TCP协议的穿透流程:
    机器布局还是和上面使用UDP的一样。现在假设客户A想和客户B建立TCP连接。
首先还是 AB分别和服务器S分别建立连接,S记录AB的互联网实际终端。然后S分别向AB发送对方的实际终端。接着,从A和B向S连接时使用的端口,AB都异步调用connect函数连接对方的实际终端(就是S告诉的终端),同时,AB双方都在同一个本地端口监听到来的连接(也可以先监听,再connect更好)。由于双方都向对方发送了connect请求(假设各自的SYN封包已经穿过了自己的NAT),因此在对方connect请求到达本地的监听端口时,路由器会认为这个请求是刚刚那个connect会话的一部分,是已经被许可的,本地监听端口就会用SYN-ACK响应,同意连接。这样,TCP穿透NAT的点对点连接就成功了。

下面是示例代码下载,VB.NET代码,演示如何用TCP协议穿透NAT实现文件传送,请用vs2005打开解决方案

http://dl2.csdn.net/down4/20070724/24133943521.rar

代码中有一个我自己封装的模仿vb6 winsock的控件ZXMSocket,这个socket可以让你设置是否使用SO_REUSEADDR参数,socket是事件驱动的。

如果你要测试代码,需要使用一个bat来启动发送和接收程序(文件格式请参照bin/Debug文件夹下的run.bat文件),这个bat的功能是以命令行的方式告诉程序登录服务器缩使用的用户名,对于服务器来说,这个用户名必须是唯一的,当然,这可能有点不科学,但是这毕竟只是一个demo。

分享到:
评论

相关推荐

    NAT穿透java

    3. **NAT穿透原理**:由于NAT的存在,两个内网设备直接通信变得复杂。NAT穿透技术(如STUN、TURN、ICE)旨在让这些设备通过第三方服务器进行间接通信,服务器作为中介,传递设备之间的IP和端口信息,从而建立直接...

    P2P之UDP穿透NAT的原理与C#实现(C#源码) 已调试成功

    2. NAT穿透原理: - 非对称NAT:当内网设备通过NAT对外发起连接时,NAT会分配一个临时的公网端口,这导致从外部回连时,公网IP和端口可能不同,形成穿透难题。 - STUN(简单Traversal of NAT):一种发现NAT映射...

    UDP穿透NAT的原理与实现

    1. 非对称NAT穿透:在非对称NAT中,出站和入站规则不同,因此需要两步建立连接。首先,客户端A通过服务器B向客户端B发送一个带有其公网IP和端口的UDP数据包。客户端B收到后,通过自己的NAT向A的公网IP和端口发送响应...

    NAT穿透解决方案

    NAT穿透是解决在私有网络(局域网)中的计算机与外部网络进行通信时,由于网络地址转换(NAT)设备的存在,使得外部网络无法直接访问内部网络设备的问题。这个问题在对等网络(P2P)通信模式中尤为突出,尤其是在...

    XMPP协议及NAT穿透介绍文档

    文档可能包含对NAT工作原理的解释、XMPP协议的详细描述,以及如何利用Jingle和NAT穿透技术来优化通信性能的实例。这些内容对于理解XMPP在复杂网络环境下的应用,以及开发相关通信软件都是非常有价值的参考资料。

    NAT穿透之NAT类型检测.pdf

    了解这些不同类型的NAT的特点及其工作原理对于成功实现NAT穿透至关重要。 #### 不同类型的NAT 1. **Full Cone NAT(完全圆锥型NAT)** - **特点**:当内部主机首次通过UDP Socket发送数据到外部主机时,NAT会为...

    基于TCP,UDP NAT穿透资料附源码

    综合这些资源,你可以深入了解NAT的工作原理,学习如何利用TCP和UDP进行NAT穿透,以及在实际的P2P系统中如何实现这些技术。这些资料对于网络编程、P2P应用开发或者网络通信研究者来说都是宝贵的学习材料。

    真正好用的nat穿透源代码,附送STUN检测代码

    本文将深入探讨NAT穿透的基本原理以及提供的源代码。 NAT是一种普遍应用于家庭和企业网络的技术,它允许一个或多个设备共享一个公共IP地址,同时通过内部网络的私有IP地址进行通信。然而,这种设置使得直接的P2P...

    P2P之UDP穿透NAT的原理与实现

    2. ICE框架:ICE是一种更全面的NAT穿透机制,结合了STUN和TURN(Traversal Using Relays around NAT)服务器。TURN服务器作为中继,当两台设备无法直接通信时,它们可以通过中继服务器转发数据。ICE会尝试各种可能的...

    P2P之UDP穿透NAT的原理与实现(增强篇).rar

    NAT穿透通常有两种方法:STUN(简单Traversal of UDP through NAT)和ICE(Interactive Connectivity Establishment)。STUN服务器提供了一个公开的IP和端口,使内网设备能够发现自己的NAT类型和外网映射。ICE则是一...

    P2p之UDP穿透NAT的原理与实现代码

    总之,P2P之UDP穿透NAT的实现涉及到网络编程、NAT工作原理以及UDP协议的特性。通过代码实现,可以学习到如何在实际环境中克服NAT对P2P通信的障碍,这对于开发分布式系统和实时通信应用具有重要意义。

    Java实现UDP穿透NAT技术

    UDP(User Datagram Protocol)是一种无连接的传输层协议,它提供了快速、简单、不可靠的数据报服务。在处理网络通信时,NAT(Network ...通过理解这些原理和Java中的实现细节,你可以构建自己的NAT穿透解决方案。

    P2P之UDP穿透NAT的原理与实现资料+源代码

    源代码通常会包含上述步骤的实现,包括套接字编程、STUN/TURN协议的处理以及NAT穿透策略的逻辑。对于初学者来说,理解并分析这些代码可以帮助深入理解P2P网络和UDP穿透NAT的工作原理。 总之,P2P中的UDP穿透NAT是...

    NAT穿透 MFC界面版

    NAT穿透技术是一种在网络地址转换(Network Address Translation)环境下实现设备间通信的...通过理解NAT穿透的基本原理和MFC的特性,开发者可以进一步优化这个程序,提高其稳定性和适应性,为更多应用场景提供服务。

    P2P 之 UDP穿透NAT的原理与实现(附源代码)

    P2P 之 UDP穿透NAT的原理与实现(附源代码)

    NAT穿透内网资料和源代码

    **NAT穿透内网技术详解*...通过学习和理解NAT穿透的原理以及相关源代码,我们可以更好地理解和解决网络通信中的各种问题,提高网络应用的效率和可靠性。对于初学者来说,这份资料和源代码是深入理解NAT穿透的宝贵资源。

    UDP实现的NAT穿透

    NAT穿透,又称为端口映射或者打洞技术,是为了让两个位于NAT后的设备能够直接通信而设计的一种技术。 NAT的工作原理是将内部网络中的私有IP地址与外部网络的公共IP地址进行映射,这样内部网络的设备可以通过一个...

    P2P 之 UDP穿透NAT的原理与实现

    P2P 之 UDP穿透NAT的原理与实现

    C# UDP NAT

    UDP(User Datagram Protocol)是一种无...对于学习网络编程和理解NAT穿透原理的开发者来说,这是一个非常有价值的资源。通过深入研究和实践,可以掌握如何在C#环境中实现可靠的UDP通信,以及如何处理NAT环境中的挑战。

Global site tag (gtag.js) - Google Analytics