上一篇中说到了“泵”在编程中的作用以及一些具体用处,但没有实际demo,可能不好理解,这篇文章我分享一个UDP通信的demo,大概实现了类似“飞鸽传书”在局域网中文本消息和文件传输的功能。功能不全也不是很完善,但足以说明“泵”在代码中的具体应用。
先来回忆一下上篇中“泵”的含义,首先它是可持续运作的,其次它可以将“数据”从一个地方传递到另外一个地方,供其他人使用。搬一张上篇的图:
图1 程序中“泵”结构图
如上图所示,每个泵有一个“待处理”的数据容器(缓冲区),泵循环里面还可以有一个“预处理”的地方,可以在数据被传递之前,先做处理,最后,泵会输出数据,供别人使用。完成“数据源”->“泵”->“使用者”这样一个过程,明显“泵”起到动力的作用。我们可以看见,“使用者”使用数据的过程包含在“泵循环”之内,也就是说,如果使用数据时,耗时太长,一次“泵循环”不能及时返回,那么,缓冲区中的数据就会累积,得不到及时处理,影响“泵”的工作效率。能解决该问题有两种途径:
- 1)在使用数据时,不做长时间耗时操作;
- 2)先不直接使用数据,先将“泵”传递出来的数据存入另外一个容器(缓冲区),再另外开辟线程去处理缓冲区中的数据。
其中1)明显治标不治本,不能解决实际问题,2)倒是可以一试,因为它将“使用数据”和“泵循环”分离开来,使“使用数据”不会直接影响到“泵”的工作。其实上一篇中说到“UDP通信结构”时就已经按照2)所说的实现的,我那时候说不能将数据处理、数据分析都放在“数据接收泵”中,因为有一个主要原因就是,那样做会影响数据接收的效率。后来我画了一张UDP通信结构图,里面用到了三个“泵”(数据接收泵、数据分析泵、数据处理泵),如下图:
图2 UDP通信中“泵”的使用
如上图,“数据分析泵”使用到了“数据接收泵”传递出来的数据,“数据处理泵”使用到了“数据分析泵”传递出来的数据,它们都没有直接使用,都是先将数据存入对应缓冲区,然后开辟新的“泵”(也是另开辟线程吧)去处理。这样一来,每个环节互不影响其他环节的工作效率。
在实现这个UDP通信demo时,我定义了三个“泵”类,一个数据发送类,和一个帮助类,分别如下:
- UDPSocket:主要实现了数据接受泵,以及socket绑定等;
- DataAnalyse:数据分析泵;
- DataDeal:数据处理泵;
- UDPSender:数据发送;
- Help.cs中一些类型:辅助功能。
其中,DataAnalyse是UDPSocket中“泵”传递出来数据的使用者,DataDeal是DataAnalyse中“泵”传递出来数据的使用者,然后我们(开发者)是DataDeal中“泵”传递出来数据的使用者。
需要说明的是,默认请款下,DataDeal中的“泵”是不会传递出来任何数据,DataAnalyse中的“泵”也不会传递出来任何数据,我们需要根据具体需求,实现自己的DataDeal和DataAnalyse类,重写Deal和Analyse虚方法。我定义了两个类,分别为MyDataDeal和MyDataAnalyse,具体代码如下:
如代码所示,各位下载源码后,可以将UDPSocket、UDPSender、DataDeal、DataAnalyse以及Help.cs文件中的一些类型封装起来,生成一个通用程序集,实际使用中,只需要引用该程序集,并且实现自己的DataDeal和DataAnalyse就行。
另外,demo中我还定义了一套自己的“通信协议”,如下:
通信协议根据具体需求而不同。
总结一下,在其他项目中具体使用步骤如下:
- 根据具体需求,定义一套“消息协议”;
- 从DataAnalyse派生出一个新的类,根据“消息协议”重写Analyse方法,进行数据分析;
- 从DataDeal派生出一个新的类,根据具体业务逻辑重写Deal方法,进行数据处理;
- 数据发送方必须严格按照“消息协议”发送数据;
- 最后,你要做的就是注册DataDeal派生类的一些事件,使用“泵”传递出来的程序可识别数据。
源码下载地址:http://files.cnblogs.com/xiaozhi_5638/UDPMessager.rar
希望对各位有帮助。附几张效果图
作者:周见智
出处:http://www.cnblogs.com/xiaozhi_5638/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。