使用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的时候只要加上这么一行:


知道上面的知识就很好办了,下面我来说说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。
转自:http://www.cnblogs.com/regedit/articles/829725.html
使用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 ...
随机推荐
- 洛谷 P1273 有线电视网 && caioj 1109 树形动态规划(TreeDP)4:比赛转播(树上分组背包总结)
从这篇博客往前到二叉苹果树都可以用分组背包做 这依赖性的问题,都可以用于这道题类似的方法来做 表示以i为根的树中取j个节点所能得的最大价值 那么每一个子树可以看成一个组,每个组里面取一个节点,两个节点 ...
- 【Codeforces Round #465 (Div. 2) C】Fifa and Fafa
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 这个x2,y2和圆心(x1,y1)相连.形成的直线和圆交于点(x3,y3) 则(x2,y2)和(x3,y3)的中点就是所求圆的圆心. ...
- poj 1681 Painter's Problem(高斯消元)
id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
- cvBoostStartTraining, cvBoostNextWeakClassifier和 cvBoostEndTraining
/****************************************************************************************\ * Boostin ...
- 【android】getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的作用
getCacheDir()方法用于获取/data/data/<application package>/cache目录 getFilesDir()方法用于获取/data/data/< ...
- 灵活的运用Model类
1.定义接口 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespac ...
- Linux下图解minicom安装
Linux下图解minicom安装 minicom是一个串口通信工具,就像Windows下的HyperTerminal.可用来与串口设备通信,如调试交换机和Modem等.它的Ubuntu软件包的名称就 ...
- Android控件-TabHost(一)
什么是TabHost? TabHost组件的主要功能是可以进行应用程序分类管理,例如:在用户使用windows操作系统的时候,经常见到如图所示的图形界面. TabHost选项卡,说到这个组件, ...
- 访问API的方式为:localhost/api/customers, 创建自定义JSON格式化器
注意的是,访问API的方式为:localhost/api/customers,在实际中将要根据情况替换合适的端口,默认所有的WEB API都是通过/api根目录的方式访问的 创建自定义JSON格式化器 ...
- HDU 3374 String Proble
String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...