其实很早我就已经实现了使用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。

使用TCP协议的NAT穿透技术 (转)相关推荐

  1. p2p网络中的NAT穿透技术----常见NAT穿越解决方案

    p2p网络中的NAT穿透技术----常见NAT穿越解决方案 常见NA丁穿越解决方案 NAT技术在缓解IPv4地址紧缺问题.构建防火墙.保证网络安全等方面都发挥了重要 作用.然而,NAT设备的广一泛存在 ...

  2. NAT穿透技术详解(udp打洞精髓附代码)

    以前自己写的代码都只是在本地进行c/s通信,今天想写一个可以跨越外网的c/s通信,这里我就用udp实现一个点对点的不同外网的通信.用到的技术就是nat穿透技术,这里最直接使用的就是udp打洞技术.文中 ...

  3. IP协议与NAT/NAPT技术

    文章目录 IP协议 一.什么是IP协议 1.IPv4协议报文格式 关于分片 2.IP地址 3.子网划分与CIDR 4.特殊的IP地址 5.公网IP和私网IP 6.IP地址的分配(DHCP) 二.NAT ...

  4. SIP协议的NAT穿越技术

    作者: Diana Cionoiu 原文: http://freshmeat.net/articles/view/2079/ 翻译:Karl Ma NAT 指的是网络地址转换(Netword Addr ...

  5. 很酷的智能家居/工业路由器两用的物联网WiFi模块 MQTT/TCP协议 MIPS+LINUX+Openwrt技术覆盖

    MT7688 支持两种运作模式:IoT gateway 模式与 IoT device 模式. 在 IoT gateway 模式中,可透过 PCIe 界面连接至 802.11ac 芯片组,并作为双频 8 ...

  6. NAT穿透之STUN和TURN技术浅析

    出自:http://blog.csdn.net/zqf_office/article/details/25338567 在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有 ...

  7. stun 协议 NAT穿透方式 简介

    STUN是RFC3489规定的一种NAT穿透方式,它采用辅助的方法探测NAT的IP和端口.毫无疑问的,它对穿越早期的NAT起了巨大的作用,并且还将继续在NAT穿透中占有一席之地. STUN的探测过程需 ...

  8. (TCP-over-UDP library)基于UDP协议之上实现通用、可靠、高效的TCP协议

    随着互联网应用广泛推广,出现了越来越多的网络应用,其中基于p2p思想的各种网络技术的产品也越来越多的出现在我们的视野当中.从最早闻名的Napster到现在的Bittorrent.eMule.skype ...

  9. STUN和TURN 网络穿透技术浅析

    在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有少部分主机能够直接接入Internet.很多时候,我们希望网络中的两台主机能够直接进行通信,即所谓的P2P通信,而不需要 ...

最新文章

  1. tensorflow---alexnet training (tflearn)
  2. why settype transport is not available in AG9 but works in AG3
  3. 使用junit-drools进行JBoss Drools单元测试
  4. 关闭报错_Cydia Impactor工具各种报错提示的解决方法!
  5. 移动应用开发者在区块链中怎么赚钱?
  6. C#,SharpGL开发的3D图表控件
  7. 最新QQDIY动态静态名片代码
  8. ubuntu默认播放器缺少解码器
  9. JS技能点--日期时间格式化
  10. 服务器构建系统发育树
  11. asterisk注册河南联通ims
  12. t检验比较两种算法的性能
  13. 斑马打印机linux驱动安装教程,linux-Zebra软件包的基本安装与配置
  14. html怎么做出相框的效果,使用CSS3制作PS级的图片边框效果
  15. 在Python应用中Telegram 机器人搭建消息提醒
  16. 将电脑输入法关闭只留我们经常用的输入法
  17. 高斯约当法求逆矩阵的算法实现(C++)
  18. C语言实现乘方运算---m的n次方(附完整源码)
  19. matlab编码流程图,高手来帮我看看该怎么画这些代码的流程图
  20. 如何写好一篇论文-02

热门文章

  1. 超赞!又挖到一批宝藏级计算机科学网站!
  2. 用手机来支付什么-支付的方式
  3. 【PaddlePaddle+OpenVINO】打造一个指哪读哪的AI“点读机”
  4. 手持两把锟斤拷,口中疾呼烫烫烫。 脚踏千朵屯屯屯,笑看万物锘锘锘。
  5. 自旋锁和互斥锁的区别 java中lock Syntronized区别
  6. mysql中sql插入时间_mysql中使用sql语句插入日期时间类型的写法
  7. PostgreSQL 存储过程(函数)创建和基本语法
  8. 基于Java开发的分布式在线教育系统,支持考试、直播、问答
  9. mybatis-generator-gui 一款 mybatis generator 的图形界面工具
  10. 想要安装pdf虚拟打印机64位应如何实现