RDP(Reliable--UDP)Library 向右看齐 2022-08-11 05:28 177阅读 0赞 ### RDP(Reliable--UDP)Library--可靠UDP传输实现方案 - 缘分天空的日志 - 网易博客 ### # 思想的小鱼 # 非生而知之者,孰能无惑?惑而不从师,其为惑也,终不解 2011-07-08 17:46:10| 分类: 学习\*路 | 标签: 此文由原创,转载请注明出处。 (全文下载)https://p-blog.csdn.net/images/p\_blog\_csdn\_net/nunixblog/EntryImages/20081015/rdp.pdf.jpg (另存为pdf格式) 一、 实现背景 在P2P产品实现中,NAT穿透是已经是很普遍的技术,其中UDP协议穿透又因其较高的成功率成为实现时的首选方案。然而由于UDP协议本身有传输不可靠的缺点,于是基于UDP协议的可靠通信就成为众多P2P产品实施的关键。 目前有一些开源库例如UDT、RUDP、RakNet、eNet等都是基于UDP协议的可靠通信开发库。然而这些库在应用中都有着各种各样的不足之处,比如大量数据传输效率不高、都未提供穿越proxy代理功能,或者对NAT穿透技术有的支持不全面。 二、 RDP开发库简介 RDP(Reliable--UDP)Library是一个基于UDP/IP协议的可靠网络通信库。RDP的设计原理参考TCP协议,使得应用程序能够在UDP层获得类似TCP的通用、可靠的数据传输能力。 RDP以源码或DLL形式提供一组简单、通用的应用程序接口(RDPSocket API)函数,用于第三方应用程序开发。RDPSocket API采用C++语言实现,支持Windows / Linux /Unix等多种系统平台,支持IPV4 / IPV6的网络环境。 三、 RDP协议 1.协议格式 RDP标志(12位:0x888) 包类型(4位) 窗口大小(16位) Socket ID (32位) SEQ Number ACK Number 。。。数据。。。 <table> <tbody></tbody> </table> 字段含义如下: RDP标志:标志RDP包,固定是 0x888。 包类型: SYN:发起连接。 SYNACK:SYN确认。 DATA:数据包。 ACK: 数据包确认。 CHECK:接收窗口检测。 PUNCH:NAT穿透。 LIV:连接保活标志。 FIN:关闭连接。 FINACK:FIN确认 窗口大小:接收端可接收数据的窗口大小。 数据:用户通过RDP传输的数据。 2.RDP状态变迁: 服务器端: CLOSED-->INIT( RDPSocket) -->OPENED(RDPBind)-->LISTENING(RDPListen) CLOSED-->INIT(Listener收到SYN) \-->OPENED(Listener收到SYNACK)-->CONNECTED(RDPAccept) 客户端: CLOSED-->INIT(RDPSocket) \-->OPENED(RDPConnect)-->CONNECTED(收到SYNACK) 主动关闭: CONNECTED-->FIN\_WAIT\_1(发送FIN)-->FIN\_WAIT\_2(收到FINACK) \-->TIME\_WAIT(收到FIN,发送FINACK)-->CLOSED 被动关闭: CONNECTED-->CLOSE\_WAIT(收到FIN,发送FINACK) \-->LAST\_ACK(发送FIN)-->CLOSED(收到FINACK) 3.连接建立: RDP建立连接类似TCP,需要三次握手过程: 1) 客户端发送一个SYN到指定服务器端口。 2)服务器回复SYNACK。 3)客户端再发SYNACK来回应服务器 4.NAT穿透: Server: 1) 启动时向Punch Server发送PUNCH包进行注册。 2) 成功后每隔2分钟发送一个PUNCH包保活。 3) 收到包含Client地址信息PUNCH包后,向Client发送LIV尝试打孔。 Cliet: 1) 启动时向Punch Server发送PUNCH包请求获得服务器地址。 2) 收到包含Server地址信息PUNCH包后,向Server发送LIV尝试打孔。 3) 收到Server发来的LIV包,即获得了正确的Server地址,准备SYN连接。 Punch Server(RDP也提供了封装好的类,第三方简单调用即可实现): 1) 收到Server的PUNCH包,经过SN确认后,返回PUNCH包通知Server 注册成功。 2)收到Client的PUNCH包,在已注册表的地址表中查找Client提供的SN 对应的Server地址,然后同时向Server和Client回应带有对方地址的 PUNCH包通知向对方打孔。 5.Proxy穿透: 在RDP开发环境下,客户端、服务端、PunchServer端都可以在提供Sock 5的代理服务器(Proxy Server)后工作,这时,各方只要和对端的Proxy Server打开的地址交换数据即可和对端建立连接。 6.连接保活: RDP连接建立之后,客户端需要每隔2分钟向服务端发送一个LIV包保持两者之间连接活动,服务端收到LIV包则回应LIV包。 7.连接关闭: RDP关闭类似TCP,需要四次握手过程: 1) 主动关闭方发送一个FIN到对端。 2)被动关闭方回应FINACK。 3)被动关闭方发送一个FIN到对端。 4)主动关闭方回应FINACK。 四、 RDP数据传输 1.RDP采用了类似TCP的滑动窗口协议+累积ACK确认机制来保证数据的高效传输,与其他协议不同,RDP的滑动窗口由静态循环顺序表实现,避免了过多的动态分配内存。 2.RDP在传输过程中拥有路径MTU发现机制来防止IP报文分片。 3.RDP无论服务端还是客户端都对外都只使用了一个UDP端口收发数据,即同一个UDP端口可以对应多个RDP Socket,这点与其他的同类库不同。 4.为了保证数据的可靠传输,RDP实现了类似TCP协议的超时与重传机制的拥塞控制算法来进行发送端的流量控制,包括RTT实时测量、慢启动算法、拥塞避免算法以及快速重传和快速恢复算法。( TCP拥塞控制算法请参看《TCP/IP协议详解》中相关内容的介绍) 。 五、 RDP Socket API: RDP Socket API函数 功能 RDPStatrup 初始化RDP资源,每个进程中只需调用一次. RDPSocket 创建一个RDPSOCKET RDPBind 绑定本地地址到一个RDPSOCKET RDPListen 等待客户端来连接 RDPAccept 接受一个连接 RDPConnect 连接到服务器端 RDPSend 发送数据 RDPRecv 接收数据 RDPCloseSocket 关闭连接 RDPSetProxyServer 给指定RDPSOCKET设定代理服务器地址 RDPSetPunchServer 给指定RDPSOCKET设定Punch Server,用于NAT穿透 RDPGetPeerName 读取连接的对端的地址信息 RDPGetSockName 读取连接的本地的地址信息 RDPCleanup 清除RDP资源,一个进程中只需调用一次 <table> <tbody></tbody> </table> 六、 Punch Server开发接口: Punch Server是包括在RDP中的NAT穿透辅助开发接口,第三方可以很方便的调用其提供的CPunchSrv 类开发一个Punch Server以配合RDP Socket API实现NAT穿透。 CPunchSrv类提供以下几个公共成员函数: RDP Socket API函数 功能 Init 初始化Punch Server. SetProxyServer 设定代理服务器 Start 启动Punch Server. Pause 暂停Punch Server Stop 停止Punch Server CheckRegistServer 检测注册过的Server是否在线 DeleteRegistServer 删除已注册的Server
还没有评论,来说两句吧...