基于UDP协议的并行多线程可靠通讯研究

时间:2022-08-07 04:39:46

基于UDP协议的并行多线程可靠通讯研究

摘要:UDP是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。C#是微软公司的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。本文将讲述基于UDP协议使用C#编程结合心跳包验证技术实现并行多线程可靠通讯。

关键词:UDP C# 并行 多线程 可靠通讯

中图分类号:I253 文献标识码:A 文章编号:

一、相关技术简介

UDP协议的全称是用户数据包协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。由于UDP的特性,具备资源消耗小、处理速度快的优点;缺点是不提供数据包分组、组装和不能对数据包进行排序,也就是说,当报文发送之后,是无法得知其是否安全完整到达目的地。

C#是微软公司的一种面向对象的、运行于.NET Framework之上的高级程序设计语言,旨在设计成为一种“简单、现代、通用”,以及面向对象的程序设计语言。C#程序被运行于.NET平台上。

目前.NET Framework已经随着Windows 8的发展到了4.5版本,本文将基于.NET Framework 4.0环境详述使用C#实现并行多线程可靠通讯的方法。

二、并行多线程可靠通讯的实现

1、线程安全集合类

在实际通讯应用中,通常要求通讯服务器端具备多线程并行处理能力。在多线程模式下,如何维护诸如客户端列表、通讯数据缓存等数据的同步和一致成为每一个开发者应该首先解决的问题。

在.NET 4.0之前,通常使用同步对象和(或)互斥对象实现多线程的同步控制,如C#的lock关键字,实际就是获取对象的互斥锁、执行代码、释放互斥锁的过程。

在.NET 4.0中,Concurrent命名空间为开发者提供了多个线程安全集合类,这些集合类将自动维护多线程并发访问时对数据的同步控制,可以从多个线程同时使用,无需开发者使用如同步或互斥的技术对数据同步进行干预。

本文将以BlockingCollection线程安全集合对象实现多线程下对客户端列表和通讯数据缓存的同时访问,数据定义如下:

private BlockingCollection _SedCache = new BlockingCollection();

private BlockingCollection _RecCache = new BlockingCollection();

private BlockingCollection _SedQue = new BlockingCollection();

private BlockingCollection _Clients = new BlockingCollection();

2、并行多线程UDP通讯

在通讯的处理上,我们将同时使用线程池对象ThreadPool和并行处理对象Parallel进行并行多线程的处理。

ThreadPool可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。无需开发者手动创建多线程,降低代码量,提高稳定性,且提供多个方法用于手动控制和维护线程池工作状态。

Parallel提供对并行循环和区域的支持,其所有公共且受保护的成员都是线程安全的,可从多个线程同时使用,符合多线程通讯时对数据同步和一致性的需求。

以发送数据为例,首先实现如下处理函数:

(1)心跳包处理函数:CheckHeartPackage

(2)发送队列处理函数:CheckSendQue

(2)发送数据函数:SendData

并行处理的调用:

Parallel.Invoke( new Action[] { CheckHeartPackage, CheckSendQue });

通过线程池发送数据:

private void CheckSendQue(){

SendQuesq;

SendQue[] sqs = _SedQue.ToArray();

for (int i = 0; i < sqs.Length; i++){

sq = sqs[i];

bool bAdd = ThreadPool.QueueUserWorkItem(SendData, sq);

if (bAdd)

_SedQue.TryTake(out sq);

}

}

3、可靠通讯的实现――心跳包

由于UDP协议提供不可靠信息传送服务特性,在通讯中,无法保证数据准确无误的送达对方,本文将讲述通过心跳包验证实现可靠通讯的方法。

心跳包包含接收缓存中的数据校验信息,包括数据发送者的IP地址、端口号、发送索引。心跳包生成后,进入发送队列供线程调度,并发送到对方。

因心跳包需要提取发送者的发送索引,故发送端在生成发送数据缓存的同时应生成一个无重复的索引(SendIndex)。

当接收到对方的心跳包后,从心跳包中可提取出对方接收缓存的校验信息,通过校验信息与本机发送缓存的对比,可检测出本机曾今发送过的数据是否全部到达对方。已经到达对方的数据应做一个标记(IsArrived = true),如果对方缺少本机的发送数据,则可再次发送。

心跳包的发送频率可根据使用环境而定,通常设置成3秒即可。

4、生命周期与异常处理

在实际通讯应用中,应为通讯增加详尽的异常处理机制,在重要的通讯场合,还应该记录发生过的所有异常,如记录通讯错误、发送失败等信息。

为避免收发缓存无限增长导致大量资源被占用从而影响主机性能,应为收发缓存增加生命周期机制,同时记录创建缓存对象的时间。在创建心跳包的时候,应首先检测收发缓存中数据的生命周期是否到期,如果到期,则从缓存中删除数据;如果是发送缓存,则还应检查该数据是否到达对方,如果未到达对方,应做异常记录。

关于生命周期的设置,接收缓存的生命周期应大于发送缓存的生命周期,确保接收缓存的数据晚于对方发送缓存删除,同时还应考虑心跳包的发送频率。如心跳包发送频率为3秒,发送缓存生命周期为10秒,接收缓存生命周期15秒。

三、面向对象可靠通讯的改进

通过以上的讨论,已经实现了基于UDP协议的并行多线程可靠通讯。

在此基础上,可在传输前增加对象序列化操作,接收到数据后执行反序列化操作,以实现面向对象的通讯。

在传输数据时,可通过使用DeflateStream类对数据流进行压缩与解压缩,以降低网络上的数据量。

参考文献:

[1].C#高级编程 清华大学出版社

[2].Microsoft Visual Studio 2010 文档

[2].百度百科

上一篇:关于剪力墙结构中的墙布置原则和设计 下一篇:基于高层建筑深基坑工程地下连续墙施工的分析