CDP――基于UDP的TCP协议实现

时间:2022-10-06 05:02:54

CDP――基于UDP的TCP协议实现

摘要:CDP协议是一种基于UDP协议之上的TCP协议实现,该协议同时具有TCP协议的通用、高效,和UDP协议的高NAT穿透成功率,可用于很多P2P网络应用的构建。

关键词:P2P;CDP;NAT 穿透;基于UDP的TCP

中图分类号:TP317文献标识码:A 文章编号:1009-3044(2007)03-10736-02

1 引言

随着互联网应用广泛推广,基于各种P2P网络技术的产品也越来越多的出现在我们的视野当中。从最早的Napster 到现在的Bittorrent、eMule、skype等产品,P2P这种网络应用模式已经从各个方面深入人心。这些产品在网络实现技术上,都以各自的方法解决着同样面临的一个问题,如何让他们的软件产品在各异的网络拓扑结构中顺利的进行P2P通信。

众所周知,在当今的网络拓扑结构中,普遍使用NAT设备来进行网络地址转换,那么如何让应用程序跨越这些NAT设备进行全双工通信,就成为非常重要的问题。实现跨越NAT 通信有很多种办法:首先是通过服务器进行转发,这是比较粗暴的方法,在用户量较大时,转发服务器需要付出相当大的代价;其次,可以使用NAT 穿透技术。而在NAT 穿透中,UDP 穿透的成功率比起TCP 穿透要高出许多[1]。因此在UDP 协议上构建一些大型的网络应用程序可能会成为很多人的需求。

由于UDP协议本身存在通信不可靠的缺点,对于基于UDP 进行可靠通信的需求就浮现出来了。目前在网络上有许多人正在做着这一工作,UDT、RakNet、eNet 等都是构建在UDP之上的网络可靠通信开发库,但这些库都是针对一些特殊应用进行设计的,不具备通用性。本文提出的CDP协议是在UDP基础之上实现的TCP协议。同时具备了TCP的通用、高效和UDP的高穿透成功率,并提供了简单易用的应用程序开发接口。

2 CDP设计目标

CDP主要的目标就是在UDP 层之上实现TCP 的协议算法,使得应用程序能够在UDP 层之上获得通用、可靠、高效的通信能力。CDP 网络开发库所实现的算法,都来自久经考验的TCP协议算法,以下协议设计部分主要讲解CDP实现中与TCP标准不同的部分。

3 CDP协议设计

CDP协议主要在以下几个方面与TCP有所不同:协议格式、连接建立(NAT UDP PUNCH模式)、保活机制、MTU发现与MSS通告。其他部分,如报文传输、流量控制、超时重传、拥塞控制等,均参照TCP协议实现[2]。下面将对几个不同部分分别进行说明。

3.1 协议格式

CDP的实现的算法虽然与TCP 实现的算法是大致相同的,但CDP 的协议格式只是从TCP协议格式获得参考,但并不完全与他相同,CDP协议格式如图1所示。

图中各字段意义分别为:

4 位首部长度:表示用户数据在数据包中的起始位置。

LIV:连接保活标志。

ACK:确认序号有效。

PSH:接收方应该尽快将这个报文段交给应用层。

RST:重置连接。

SYN:同步序号,用来发起一个连接。

FIN:发端完成发送任务。

16 位窗口大小:接收端可接收数据的窗口大小。

选项:只有一个选项字段,为最长报文大小,即MSS。CDP 选项格式与TCP 选项格式一致,kind=0 时表示选项结束,kind=1 时表示无操作,kind=2 时表示最大报文段长度。如下图:

图2 CDP选项字段

数据:用户通过CDP 传输的数据。

3.2 连接建立(NAT UDP PUNCH模式)

一般情况下,CDP连接的建立过程与TCP相同。但当CDP工作在UDP NAT 穿透(NAT UDP PUNCH)模式下时,在三次握手之前,先要向对端NAT 端口及预测端口以默认2ms的间隔发送默认为10个LIV报文,一来用于打开自已的NAT 端口,二来是用于进入对端NAT端口。默认值可以由用户程序设置。这时的LIV 报文中初始序号及确认序号都为0。

当接收到对端LIV 报文后,CDP立即停止LIV 报文发送,发出SYN 报文进行连接建立。这时有两种可能:一是对端直到接收到该SYN 报文,都没有接收到LIV 报文,或是刚接收到LIV报文,但没有来得及发送SYN 报文,此时将会和一般模式下连接建立的过程一致,经历三次握手;二是对端在接收到该SYN 报文之前,也已经发送SYN报文,此时双方都需要对SYN 报文段进行确认。

3.3 半打开连接及连接保活

半打开连接是指对端异常关闭,如网线拔掉、突然断电等情况导致一端关闭,而另一端却认为连接仍处于打开当中,这种情况称之为半打开连接。CDP中的一个TDP SOCKET描述符由本地IP、本地端口、远端IP、远端端口唯一确定。当远端客户端连接请求到来时,服务端将接收到一个新的CDP SOCKET描述符,当这一个描述符唯一确定信息已经存在时,对新的连接请求发送RST 报文段,通知其重置连接请求。对于旧的连接,由保活机制自动发现是否为半打开连接,如果是半打开连接,则自动关闭该连接。CDP的RST 报文与TCP 中的RST 报文是不一样的。

连接建立之后,CDP 连接需要启动保活机制。TCP 连接在没有数据通信的情况下也能保持连接,但CDP 连接不行。CDP 连接在一定时间内如果没有数据交互的话,将主动发送保活LIV报文段。这个时间根据CDP 连接工作模块不同有所差异,在NAT UDP PUNCH 模式下,默认值为1 分钟(大多数的NAT中,UDP会话超时时间为2-5分钟左右);而在常规模块下这个时间段默认值为5分钟。默认值可以由用户程序设置,用户程序需要指明两种模式下的保活时间周期。

3.4 路径MTU 发现及MSS 通告

CDP连接建立过程中会通告初始MSS(Maximum Segment Size),这个值可以由用户程序进行设置。但这个初始值是静态的,当通信双方跨越多个网络时,使用设置的MSS可能导致传输的IP 报文分片的产生。为了避免分片,CDP在数据传输过程中进行动态的路径MTU(Maximum Transmission Unit)发现,并进行MSS 的更新及通告。

CDP创建UDP SOCKET时,即将IP选项设置为不允许分片: Setsockopt(clientSock, IPPROTO_IP, IP_DONTFRAGMENT, (char*)&dwFlags, sizeof(dwFlag) )。

在发送数据时先以当前MSS 大小进行发送,如果返回值为错误码WSAEMSGSIZE(10040),则表示为报文尺寸大于MTU,需要进行IP 分片传输。此时,缩减MSS大小再次发送,直至不再返回错误码WSAEMSGSIZE(10040)。当MSS 变更并能成功发送报文后,需要向对端通报新的MSS 值。每次MSS 缩小后,默认隔30 秒,CDP 将默认扩大MSS 大小,以检查是否路径MTU 是否增大了,之后隔30*2 秒、30*2*2 秒进行检测,如果三次都未发现MTU 增大则停止进行检测。网络中MTU 值的个数是有限的[3]。因此MSS 的扩大及缩减,可依据一些由近似值按序构成的表,依照此表索引进行MSS 值的扩大与缩减计算。

CDP 中MSS 与MTU 之间关系的计算公式如下:MSS = MTUC20(IP首部)C8(UDP首部)C12(CDP首部)。

4 CDP应用程序开发接口(CDP Socket API)

使用CDP进行网络程序开发是非常容易的,它API与标准socket API是非常相似的,对应功能的函数名称都相同,只是CDP的所有API都处于名称空间CDP 之下。此程序库的实现也参考了BSD Socket的实现。CDP Socket API列表如下:

5 结束语

本文提出了一种基于UDP协议之上的TCP协议实现――CDP协议,并对现实的一些关键部分进行了讨论,最后给出了CDP协议的应用开发接口。CDP协议同时具备了TCP通用、高效的特点,有利用的UDP的NAT穿透特性,可广泛应用与构建各种P2P网络应用。

参考文献:

[1]B. Ford, P. Srisuresh, D. Kegel, Peer-to-Peer Communication across Network Address Translators [EB/OL], draft-ford-midcom-p2p,/pub/net/p2pnat, June 2004.

[2]W.Richard Stevens, 范建华,译,TCP/IP详解――卷Ⅰ:协议[M],机械工业出版社,2000.4.1.

[3]J. Mogul, S. Deering, "Path MTU Discovery"[S], RFC1191, November 1990.

本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。

上一篇:基于数据驱动的Web应用程序的构建 下一篇:MPLS网络规划与快速重路由技术的应用