一种简单的UDP网络重传机制

工作一年多,在技术层面上一直没有太大的成就。总感觉每天都在重复着一件事情,需求,改,需求,再改。在这种重复中,开始变得有些暴躁。很希望能也有所突破,今天刚刚开通了CSDN博客。决定在这个满是大牛的平台上,留下自己的每一点学习过程,也在大家面前呈现自己的编程错误和误区。希望各位大牛能不惜赐教,对文章中有的错误一定要指出来,这会是我最大的收获。

前段时间,经手一个网络相关软件的开发。由于是新手,在接触到这个项目的时候一时没有太多的头绪。其中有一个关于UDP网络传输中的重传问题,思考了好久自己只能想到一个很耗费资源和调度的方法。最初的想法是这样的:

功能要求是消息发送间隔1秒,需要有三次重传的机制,当超过三次则改发送间隔为3秒。

1、建立消息处理结构:包括消息ID、消息状态(是否发送成功)、重传次数、重传超时时间。

2、建立接收消息线程,当受到消息时,通过消息的ID将消息的状态设定为发送成功。

3、建立发送消息方法,将消息加入发送队列,调用线程循环:判断消息状态(break)、发送消息、sleep、重传次数++、判断重传次数,修改sleep时间。


如此一来,虽说实现了消息的发送,但是对于程序的执行起来,每一次发送都需要新起调用线程进行处理。一来程序的开销变得很大;二来,受Windows系统线程最大数量的限制,当连续收发一段时间之后软件最终崩溃了。查询得知可能是系统限制上的问题之后,居然考虑到了调用线程池的方式来处理这样的问题。在进行过一番尝试之后,发现这样的处理只是使这一块的调度变得很是复杂,且多线程之间的数据同步也出现了问题。后来在老大的建议和方案之下,进行了如下的改进。这里就用简单的代码进行说明下。

class Message
{
    public int Status { get; set; }	//记录消息的发送状态
    public DateTime SendTime { get; set; }	//记录消息发送的时间
    public int SendCounts { get; set; }	//记录消息发送的次数
    public int TimeOut { get; set; }		//超时时间
    ...					//其他与消息有关的项
}

在消息发送处理的同一事务中(注:事务在循环执行)。查询当前时间和消息发送时间的差值。

if (msg.Status != SUCCESS)		//判断是否发送成功
{
    TimeSpan span = DateTime.Now - msg.SendTime;
    int total = span.TotalSeconds;		//获取到当前距离发送时间的秒数。
    if (total >= msg.TimeOut)
    {
        send(msg);
        msg.SendTime = DateTime.Now;
        msg.SendCounts++;
        if (msg.SendCounts >= 3)
        {
            msg.TimeOut = 3;
        }
    }
}

这样当事务在循环体执行的时候会检测消息是否发送成功,也会根据发送时间来判断处理超时重发和超时将时间延长的处理了。

上面的代码根据脑海中存留的思路进行书写的,可能在正式的使用中会出现很多问题。这里只是将这个处理过程写下来,希望能得到好的建议和改进优化的方法。

猜你喜欢

转载自blog.csdn.net/HappyCF/article/details/43456357