使用TCP协议的NAT穿透技术(转)
其实很早我就已经实现了使用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的点对点连接就成功了。
使用TCP协议的NAT穿透技术(转)的更多相关文章
- 使用TCP协议的NAT穿透技术
一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基本上没有人会告诉你如何使用TCP协议去穿透(甚至有的人会直接告诉你TCP协议是无法实现穿透的).但是,众所周知的是,UDP是一个无连 ...
- 使用TCP协议的NAT穿透技术 (转载)
其实很早我就已经实现了使用TCP协议穿透NAT了,但是苦于一直没有时间,所以没有写出来,现在终于放假有一点空闲,于是写出来共享之. 一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基 ...
- 网络协议之NAT穿透
NAT IPv4地址只有32位,最多只能提供大致42.9亿个唯一IP地址,当设备越来越多时,IP地址变得越来越稀缺,不能为每个设备都分配一个IP地址.于是,作为NAT规范就出现了.NAT(Networ ...
- p2p网络中的NAT穿透技术----常见NAT穿越解决方案
转:http://blog.csdn.net/cllzw/article/details/46438257 常见NA丁穿越解决方案 NAT技术在缓解IPv4地址紧缺问题.构建防火墙.保证网络安全等方面 ...
- WebRTC下 的 NAT 穿透技术
NAT的概念模型 NAT名字很准确,网络地址转换,就是替换IP报文头部的地址信息.NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址提供公网可达性和上层协议的连接能力. ...
- NAT穿透解决方案介绍
最近公司要实现在各种网络环境下面的多屏互动(机顶盒.android phone.iphone及PC端)的需求:由于IP地址资源有限的原因,目前我们使用的各种终端设备都位于局域网后面也就是多台设备共享同 ...
- NAT穿透解决
1.各种网络环境下的P2P通信解决方法: (1)如果通信双方在同一个局域网内,这种情况下可以不借助任何外力直接通过内网地址通信即可: (2)如果通信双方都在有独立的公网地址,这种情况下当然可以不借 ...
- NAT穿透解决方案介绍(转)--Java ICE实现
转:http://www.cnblogs.com/javaminer/p/3575282.html 最近公司要实现在各种网络环境下面的多屏互动(机顶盒.android phone.iphone及PC端 ...
- NAT穿透的方式
目前主要的NAT类型有如下几种: 1)Full-cone NAT, also known as one-to-one NAT 一旦一个内网地址 (iAddr:iPort) 被映射到一个外部地址 (eA ...
随机推荐
- [转载]CentOS6 快速搭建轻量级远程桌面 Xfce&nb
原文地址:CentOS6 快速搭建轻量级远程桌面 Xfce & VNC & Firefox作者:哈囉健一 0.系统信息 CentOS Linux release 6.0 (Final) ...
- CentOS设置开机自动启动某服务
CentOS设置开机自动启动某服务 这里以启动sshd服务为例: 查看sshd是否已经是系统服务: # chkconfig --list |grep sshd 会显示: sshd ...
- tensorflow没有代码提示的问题
在tensorflow包下的__init__.py文件中定义了一个contrib变量表示tensorflow.contrib包下的内容,但是tensorflow.contrib这个包是懒加载的,也就是 ...
- 开发 Swift 和 Objective-C 混编的 Framework
来源:黄文臣 blog.csdn.net/hello_hwc/article/details/58320433 前言 为什么要写这样一篇文章,因为昨天和一个朋友讨论到Swift和Objective C ...
- YAML 语言教程(转载)
用YAML语言读取配置是最快的,之前的suricata中用yaml读取了配置,并且在代码运行期间,对配置进行了维护,所以抽点时间,来了解一下YAML语言编程,下文虽然对YAML语言和JAVAScrip ...
- golang学习笔记 ---TCMalloc
图解 TCMalloc 前言 TCMalloc 是 Google 开发的内存分配器,在不少项目中都有使用,例如在 Golang 中就使用了类似的算法进行内存分配.它具有现代化内存分配器的基本特征:对抗 ...
- Java Nashorn--Part 6
Nashorn 的 JavaScript 语言的扩展 正如我们所讨论的,Nashorn 是一个完全符合 ECMAScript 5.1 的实现.然而除此之外,Nashorn 还实现了很多 JavaScr ...
- Python 文件 next() 方法
描述 Python 3 中的 文件 对象不支持 next() 方法. Python 3 的内置函数 next() 通过迭代器调用 __next__() 方法返回下一项. 在循环中,next()方法会在 ...
- JVM 入门三板斧
一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的.类加载器读取了类文件后,需要把类.方法.常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存分为三部分: Young Ge ...
- Python 爬虫 数据清洗 去掉 超链接
有时候我们需要清洗数据,里面有超链接,怎么去掉他们,比如下面的问题 , - January , </p></li><li </p><div " ...