UDT协议实现分析总结

UDT的整体结构

UDT Socket是UDT中的核心,同时它也是一座桥梁,它将UDT的使用者应用程序与内部实现部分对于数据结构的管理、网络数据的传输连接起来。

应用程序通过它将数据放进发送缓冲待发送,或者借由它来获取从网络接收数据。而与网络进行交互的部分,则从它那里拿到要发送的数据进行发送,或者在收到packet时将packet dispatch给它。

UDT的数据接收部分框架:

UDT的数据发送部分框架:

UDT的一些问题

1. 接口的合理性。

分析了UDT的这许多code,给人的感觉就是,socket接口设计的似乎并不是特别的合理。socket的两种类型,即用于进行数据传输的socket和服务器端用于接受连接的socket,两者之间的差别非常的明显。它们所能提供的操作,它们的状态转换过程都很不一样,服务器端用于接受连接的socket支持listen和accept操作,而用于进行数据收发的socket则不支持;同样用于进行数据收发的socket支持send和recv,服务器端用于接受连接的socket则不支持。但当前的socket接口统一用一个socket来表示。也就是有多种其实毫不相干的职责都被堆在一个socket结构上了。

socket接口这样的设计所带来的问题就是使用起来比较容易混淆,对用户的友好度比较低。即在执行某个操作之后才能通过返回值检测出来,而不能在调用函数时,就通过编译error之类的提前报出来。而实现起来呢,则不得不增添许多额外的状态检查,大大增加了实现的复杂度。

2. 有些地方存在大段大段的重复code。

比如CUDTUnited::updateMux()函数,CUDTUnited的两个bind()函数之间,CUDT::sendmsg()和CUDT::send()中等待发送缓冲区有空间部分的code,CUDT中两个connect()函数中初始化CUDT的操作等等。

3. 在CUDT中竟然用了m_bOpened,m_bListening等8个bool变量来表示UDT Socket的状态,这使得状态管理的复杂度大为增加。

4. Code中还是有一些历史遗留问题,比如DelayWarning/CongestionWarning消息,定时器中对于NAK消息的发送等,这些机制被移除掉,但是又被移除的不是很彻底。

5. 消息类型这种本应该定义为enum或者类似的东西的常量,却是magic number满天飞。

Done。

时间: 2024-08-11 08:28:04

UDT协议实现分析总结的相关文章

UDT协议实现分析——数据的接收

看了UDT中数据发送的部分之后,我们转换一个角度,来看一下接收端发生的故事. 如我们前面在 UDT协议实现分析--连接的建立 一文中看到的那样,CUDT在connect()的后半场,会通过调用CRcvQueue::removeConnector()把它自己从它的CChannel的接收队列CRcvQueue的m_pRendezvousQueue队列中移除出去,以表示连接已成功建立,后面不再通过m_pRendezvousQueue接收连接相关消息,并通过调用CRcvQueue::setNewEntr

UDT协议实现分析——UDT Socket的创建

UDT API的用法 在分析 连接的建立过程 之前,先来看一下UDT API的用法.在UDT网络中,通常要有一个UDT Server监听在某台机器的某个UDP端口上,等待客户端的连接:有一个或多个客户端连接UDT Server:UDT Server接收到来自客户端的连接请求后,创建另外一个单独的UDT Socket用于与该客户端进行通信. 先来看一下UDT Server的简单的实现,UDT的开发者已经提供了一些demo程序可供参考,位于app/目录下. #include <unistd.h>

UDT协议实现分析——数据的发送

连接建立起来之后,我们就可以通过UDT Socket进行数据的收发了.先来看用来发送数据的几个函数.UDT提供了如下的几个函数用于不同目的下的数据发送: UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags); UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false); UDT_API i

UDT协议实现分析——连接的建立

UDT Server在执行UDT::listen()之后,就可以接受其它节点的连接请求了.这里我们研究一下UDT连接建立的过程. 连接的发起 来看连接的发起方.如前面我们看到的那样,UDT Client创建一个Socket,可以将该Socket绑定到某个端口,也可以不绑定,然后就可以调用UDT::connect()将这个Socket连接到UDT Server了.来看UDT::connect()的定义(src/api.cpp): int CUDTUnited::connect(const UDTS

UDT协议实现分析——UDT数据收发的可靠性保障

不管是数据的发送还是数据的接收,大体的流程我们基本上是都理了一下,还分析了数据收发过程中用的数据结构,接下来就看一些UDT中数据收发更精细的一些控制. UDT数据收发的可靠性保障 来看一下UDT中数据收发的可靠性保障. 接收包丢失列表CRcvLossList 先来看一下CRcvLossList的定义: class CRcvLossList { public: CRcvLossList(int size = 1024); ~CRcvLossList(); // Functionality: //

UDT协议实现分析——UDT初始化和销毁

UDT协议是一个用于在告诉Internet上传输大量数据的基于UDP的可靠传输协议. 我们可以将UDT协议的实现看作一个比较复杂的状态机.更准确的说,是一个主状态机,外加多个子状态机.主状态机是指协议实现中全局唯一.全局共享的状态与数据结构,主要对应于CUDTUnited类.子状态机则是对于一次UDT连接或一个Listening的UDT Server的抽象,是UDT自己创建的Socket抽象,一个与系统socket相似但又不同的概念,主要对应于CUDTSocket和CUDT类.UDT的Socke

UDT协议实现分析——bind、listen与accept

UDT Server启动之后,基于UDT协议的UDP数据可靠传输才成为可能,因而接下来分析与UDT Server有关的几个主要API的实现,来了解下UDT Server是如何listening在特定UDP端口上的.主要有UDT::bind(),UDT::listen()和UDT::accept()等几个函数. bind过程 通常UDT Server在创建UDT Socket之后,首先就要调用UDT::bind(),与一个特定的本地UDP端口地址进行绑定,以便可以在希望的端口上监听.这里来看一下U

UDT协议实现分析——发送窗口大小及发送速率的调整

UDT主要通过在数据收发的过程中进行精细的控制来实现对于网络带宽更加有效的利用,并使网络中数据传输的速率尽可能快. 如我们前面在分析数据发送的控制中看到的,对于正常的顺序packet发送,发送控制主要在于两个方面,一是发送窗口的大小,也就是某个时刻已经发送但未得到相应的packet的最大个数,这一点主要由拥塞窗口大小m_dCongestionWindow和滑动窗口大小m_iFlowWindowSize来描述,发送窗口大小为两者中较小的那一个:二是控制两个数据包发送的时间间隔,也就是包的发送速率,

UDT协议实现分析——数据发送控制

在前文中,我们有看到,数据发送的过程,大体是发送者CUDT将要发送的数据放进它的CSndBuffer m_pSndBuffer,并将它自己添加进它的CSndQueue m_pSndQueue的CSndUList m_pSndUList的堆里,后面CSndQueue m_pSndQueue的worker线程会通过CSndUList::pop()从CSndUList m_pSndUList的堆顶CUDT中获取一个要发送的包来发送,包的获取主要是通过CUDT::packData()来完成,而这个函数正