首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

可靠UDP传输的实现!解决思路

2012-04-04 
可靠UDP传输的实现!一直纠结于UDP的可靠传输,在查看了UDT的相关介绍后,发现并不是我需要的,我需要的是一个

可靠UDP传输的实现!
一直纠结于UDP的可靠传输,在查看了UDT的相关介绍后,发现并不是我需要的,我需要的是一个可以进行多点传输的的可靠UDP。最终,还是自己慢慢把它完成了,虽然还不够好,不过总算出来个框架了,以后改就容易了 。
  在算法上并没有什么特别的,就是不断的采用超时重发机制。在发送端,建立了一个庞大的发送缓冲区队列,每个发送过的发送单元都将自动被添加到这个发送缓冲区中,然后由维护线程来管理。在维护线程中,定时遍历所有的发送缓冲区,检查那些没有被确认且还没达到发送最大值限制的发送单元,然后将它们发送出去,以此类推,直到所有的发送单元都被确认或者都达到发送最大值限制。请看下面的发送单元结构:

C/C++ code
     //发送单元typedef struct _UDT_SND_ITEM_{ USHORT           uBufLen;               //chBuf的数据长度 USHORT           uLimitCnt;             //发送次数限制 SOCKET           hSock;                 //UDP句柄 CHAR                chBuf[DATA_BUFSIZE];   //要发送的数据,UDT头 + 数据 DWORD            dwLastTime;            //最后发送时间(如果为0xFFFFFFFF则表示已经确认)  SOCKADDR_IN      To;                    //发送的目的地}UDT_SND_ITEM;
在CUDTSend类中的变量 DWORD * m_pdwPos是用来维护发送单元的集合,当UDTSend函数将一个要发送的数据包拆分成独立的发送单元并发送时,都会依据这个发送单元的序号将该发送单元添加到m_pdwPos集合中,使该集合中的对应序号的地址就是这个发送单元。目前这个发送缓冲区的最大容量使65536,也就是最大可以存储65536个未确认的发送单元。
  相比之下,接收类的设计就显的比较复杂,因为接收类要考虑来自不同主机所发送过来的数据,还要考虑每个主机发送的不同数据包,并且就算是同一个数据包,也还要按顺序接收每个单元数据,在组合这些单元数据为一个整数据包,针对以上问题,我通过定义以下的数据结构来完成功能:
C/C++ code
//接收包单元typedef struct _UDT_RECV_ITEM_{ DWORD              dwSeq;                   //序号 DWORD              uRecvLen;               //数据长度 CHAR               chBuf[DATA_SNDSIZE];    //数据部分}UDT_RECV_ITEM;


 
C/C++ code
//数据包(接收单元的组合)typedef struct _UDT_RECV_ITEMS_{    DWORD                dwSeqSpan;               //包序号区间 USHORT               uPacketCount;            //包数量来自于包区间序号相减 USHORT               uRecvCount;              //已经接收的包数量 DWORD                dwLastTime;              //最后接收到包的时间 CCriticalSection     cs_item;                 //接收单元同步对象 DWORD                dwItemPos[1024];         //所有接收包单元集合 _UDT_RECV_ITEMS_   * ItemsNext;               //指向下一个ITEMS结构}UDT_RECV_ITEMS;

C/C++ code
//主机结点(每个接收的主机信息)typedef struct _UDT_RECV_PEER_{ SOCKADDR_IN         Peer;                    //发送端 DWORD               dwLastTime;              //最后更新时间 CCriticalSection    cs_items;                //包表示同步对象    _UDT_RECV_ITEMS_  * ItemsNext;               //指向下一个ITEMS结构    _UDT_RECV_PEER_   * PeerNext;                //指向下一个节点}UDT_RECV_PEER;

以上三个结构通过以下示意图的方式连接起来,实现收包的功能
UDT_RECV_PEER ——> UDT_RECV_PEER ——> UDT_RECV_PEER ——>.......  
  |  
  |  
  V
UDT_RECV_ITEMS——>UDT_RECV_ITEM——>UDT_RECV_ITEM——>......
  |
  |
  V
UDT_RECV_ITEMS
  |
  |
  V
UDT_RECV_ITEMS
  |
  |
  V
  ......

以上示意图的意思是说,如果收到的数据包来自不同的主机节点都会添加一个UDT_RECV_PEER节点形成一个主机节点链表,针对与每个主机可能会收到不同的数据包,采用在主机节点下串联UDT_RECV_ITEMS结构的方法存放数据包,针对每个接收包单元会存放在UDT_RECV_ITEMS结构下的dwItemPos[1024]成员中,该成员的每个元素都可以用来存放UDT_RECV_ITEM接收单元。以这样的结构来完成数据包的可靠接收,并完成从单一的接收单元组合成完整的数据包的过程,这整个过程都通过调用CUDTRecv类的UDTRecv函数来完成,该函数完成了从接收数据,到发送确认,再到存储接收单元,最后实现组包这一系列过程,并通过输出参数将接收到的数据包返回给调用者。

  综合以上的说明,不难看出,虽然实现了可靠传输,但是并没有实现完全的可靠传输,因为受到发送缓冲的序号限制,最大只能同时存在65536个发送包,也就是说如果在整个发送过程中同时存在的未确认包超过这个限制,就会使发送包出现错误,并导致数据无法可靠传输;而且由于是尽可能的可到传输(限次发送),所以如果遇到网络情况恶劣的情况下,可能会导致部分发送数据超过发送最大值限制而被清除;因此这里介绍的可到传输以及相关代码只是实现了一个框架,并可以满足大部分情况,如果要满足所有情况,则需要不断的修改完善。

相关代码:点击下载

[解决办法]

[解决办法]
一定要支持!
[解决办法]
一定要支持
[解决办法]
以前用组播做过多点文件传输。支持下。
[解决办法]
需要的是一个可以进行多点传输的的可靠UDP-----我的理解是,一对多的传输,或者是多对1的传输。对于UDT的实现,他实现的是TCP的方式。对于1对多的传输他其实已经实现,只是可能你理解上存在问题。

对于1对多来说,多个UDT联接,其实还是占用的是一个PORT,这是对于服务器来说,多个对同一个PORT发送,UDT是完全支持的。
而对于客户就是占用了多个PORT,这是他的问题,不能满足你的要求。

在这里我不得不提一下,UDX协议www.goodudx.com,他完全是满足你的想法的。

想实现你的想法,这个工作本身是一个复杂的过程,当你完全都实现时,其工作量是非常大的。我建议,你还是先从简单出发,然后再复合起来,复杂化。
先做点对点,再实现1对多,多对1,其实就是包的一个设计,和IP + PORT的一个变化。
[解决办法]
楼主真是强啊!
[解决办法]

[解决办法]
支持楼主,楼主能不能回答这样一个问题:你写的这个库相对于TCP有什么优点(假设有足够的时间将其完善)?
[解决办法]
资源分...
[解决办法]
帮你推荐一下~
[解决办法]

探讨

支持楼主,楼主能不能回答这样一个问题:你写的这个库相对于TCP有什么优点(假设有足够的时间将其完善)?

[解决办法]
探讨
支持楼主,楼主能不能回答这样一个问题:你写的这个库相对于TCP有什么优点(假设有足够的时间将其完善)?

[解决办法]
udp的可靠传输,就是要靠重传机制
[解决办法]
游戏udp的可靠传输,就是要靠重传机制
[解决办法]
好啊 支持
[解决办法]
xsdfgvhjnlk,;,kmjinhuygtfrdsexdcfvgbhjnkl,
[解决办法]
不错
[解决办法]
支持原创!
[解决办法]
有一个地方不太明白:
当收到数据包时怎么知道,应该把哪一个数据包清除呢(因为服务器可能会连续向某一IP地址发不同的包),是不是应该在发送数据包结构中标识一下,加一个序列号?

还是说我理解有问题?
[解决办法]
能支持多大数据量传输?
[解决办法]
比tcp好在哪了
[解决办法]
探讨

支持楼主,楼主能不能回答这样一个问题:你写的这个库相对于TCP有什么优点(假设有足够的时间将其完善)?

[解决办法]

[解决办法]
这个必须顶 原来也想弄 一直不得要领
收藏了
[解决办法]
这个很强大啊,编程思路学习~~~
[解决办法]
很强大啊,编程思路学习~~~ 
 

[解决办法]
来的人不多啊
------解决方案--------------------


强烈推荐楼主看一下RAKNET 
再者一对一和一对多有什么区别吗 一对多也是在一对一得基础上实现的
[解决办法]
下载了,有时间看看
[解决办法]
楼主, 你实现的这个可靠传输UDP, 我大致的看了下, 基本上就是一个简单的SFTP的实现, 还不能说是TCP的实现, 
TCP包括最重要的拥塞控制.

你所说的多点穿透, UDT是可以实现的.


[解决办法]
上面打错了, TFTP协议...
[解决办法]
以前用过UDT,BUG好多,当服务器老崩溃
[解决办法]
重传!
[解决办法]
不懂

说白了就是把TCP的传输机制拿过来不就行了,用得着自己实现一个“可靠”吗?
实现来实现去不又是一个TCP
[解决办法]

探讨

不懂

说白了就是把TCP的传输机制拿过来不就行了,用得着自己实现一个“可靠”吗?
实现来实现去不又是一个TCP

[解决办法]
learning......
[解决办法]
正式我需要的,谢谢
[解决办法]
learnning........
[解决办法]
楼主真是强啊!
[解决办法]
好文章
[解决办法]
向楼主学习了~现在最多也就会使用简单的udp协议传输。。。看来路还很长很长啊~
[解决办法]

[解决办法]
udp可靠传输,steven的unix网络编程中有所论述,不过要自己实现可靠传输相关机制,是在应用层的,相信没有几个人敢在内核改动,还是老实的用tcp吧
[解决办法]
标记先!!
[解决办法]
484
[解决办法]
想法不一样,俺不用udp。

热点排行