我们已经积累了这样的经验:如果有一个大块的数据需要通过Tcp发送,我们会采用异步的方式以避免当前工作线程阻塞。那么,如果我们有多个线程需要同时发送大块的数据了?每个线程都在NetworkStream或Socket上提交异步发送数据的请求会导致数据发送的混乱(多个线程同时在一个Socket上进行写操作),所以,我引入了前面介绍的线程安全的网络流。在引入这个类后,似乎日子已经很好过了,但是新的功能要求使得我需要寻找另外的解决方案。
    考虑一下这个情景:我们的即时通信软件AgileIM在和好友进行视频聊天的同时,还要传递文字信息、音频数据、重要文件数据、控制命令等。而需要被传送的这些信息是有优先级顺序的,比如,控制命令的优先级最高,文件数据的优先级较低,而视频数据/音频数据在网络特别繁忙的时候是可以丢弃的。为了管理这些优先级,仅仅依靠ISafeNetworkStream已经不能满足我们的要求,我们需要另外一个组件来为我们解决这个问题,ESFramework提供的ITcpAutoSender组件正是为此目的的。

我们知道,在多线程的环境中对像Socket这样临界资源的访问必须保证线程安全,从另外一个角度来看,可以这么说,对某个临界资源的访问必须是同步的或者说必须是“仿单线程”的。 ITcpAutoSender就利用了这一“仿单线程”特性使的问题简单化。我们来看看这个组件究竟是如何工作的?
    我们的应用程序中的各个线程当有数据需要发送时,就将数据提交ITcpAutoSender,提交时必须指定该数据的优先级。ITcpAutoSender组件会根据指定的优先级将该数据放入到对应的队列中,请注意,将要发送的数据提交给ITcpAutoSender必须是线程安全的,这点已经由ITcpAutoSender组件保证,使用者不用关心。

ITcpAutoSender内部有一个循环线程,每次从高优先级的队列中选取一个数据包进行发送,当高优先级队列为空时,再去发送次高优先级队列中的数据。每当一个数据包发送完毕,就再从高优先级的队列开始检查,如此反复。
    从上面的描述已经可以看出,ITcpAutoSender组件仅仅是在一个线程中发送数据,所以ITcpAutoSender组件不需要再借助ISafeNetworkStream组件,而是直接使用NetworkStream就可以了。那么是不是ESFramework就不需要提供ISafeNetworkStream组件了?不是。在ESFramework框架中,ISafeNetworkStream组件主要用于服务端,因为通常情况下,服务端主动发送数据给客户端的几率比较小,而且服务端要管理成千上万的连接,所以使用ISafeNetworkStream组件是非常合适的。而ITcpAutoSender组件最常用于客户端,为客户端应用提供发送的数据的优先级机制。如果对你的应用中的客户端来说,所有的数据的优先级是一样的,那么就没有必要使用ITcpAutoSender组件了,直接使用ISafeNetworkStream就可以了。
 
    在ESFramework框架中,将数据的优先级分为4等,如下枚举定义所示:

1     public enum DataPriority
2     {
3         High ,//紧急命令
4         Common ,//如普通消息,如聊天消息
5         Low ,//如文件传输
6         CanBeDiscarded //如视频数据、音频数据
7     }

对于每个优先级,ITcpAutoSender组件的实现中都有一个对应的队列,每个队列都设置了初始大小。对于前三个优先级队列,当它们Full的时候,应用中的线程再提交数据就必须阻塞等待。而对于最低优先级CanBeDiscarded的队列,如果Full的时候有数据提交过来,则会删除队列头部的待发送数据。下面给出ITcpAutoSender组件的接口定义:
   

 1     public interface ITcpAutoSender :IDisposable
 2     {
 3         void Initialize() ;
 4         void SendData(byte[] data, DataPriority dataPriority);      
 5         void ClearQueue(DataPriority queueType) ;
 6         event CbDataDiscarded DataDiscarded;
 7         event CbDataLacked    DataLacked;
 8         event CbSimple        ConnectionInterrupted ;
 9 
10         int QueueSizeOfDiscarded { get; set;}
11         int QueueSizeOfNonDiscarded { get; set;}
12         NetworkStream NetworkStream { set;}
13     }    
14 
15     public delegate void CbDataDiscarded(byte[] data) ;
16     public delegate void CbDataLacked() ;

注意,这个接口中发布DataDiscarded事件和DataLacked事件,当网络繁忙有数据被抛弃时,DataDiscarded事件被触发;当所有的待发送队列都为空时,DataLacked事件被触发。我们的应用可以预定这两个事件来作些适当的调度。比如在AgileIM中,当DataDiscarded事件发生时,就适当减少视频捕获的帧率;当DataLacked事件发生时,就适当增大视频捕获的帧率,以达到更好的视频会话效果。

最后,说一下,很多朋友想得到ESFramework的源代码,这要等到ESFramework开源以后,相信这不是很久远的事情了。这里,我把ESFramework.dll提供给大家下载适用,当然你也可以用反射工具看看其中的构造。如果你想在你的项目中使用ESFramework,我将非常乐意回答你遇到的各种问题,你可以通过AgileSoft@163.com联系我。
    谢谢关注!

上一篇文章:ESFramework介绍之(15)-- IRAS

转到  :ESFramework 可复用的通信框架(序)

ESFramework介绍之(16)―― Tcp数据自动发送器ITcpAutoSender相关推荐

  1. 大规模时间序列数据自动异常检测架构

    Yahoo大规模时列数据异常检测技术及其高性能可伸缩架构 本文已经在InfoQ首发 本文是Yahoo在ACM国际会议上发布的一篇关于时序数据自动异常检测上的学术论文,对在智能监控尤其是趋势预测.异常数 ...

  2. 数据服务器数据自动备份工具,网站数据自动备份工具介绍

    12月的寒风吹过,站长无时无刻不在担心网站,会不会在下一分钟就被关闭.而此时,为了防止服务器机房断网,网站被迫关闭,网站的数据备份就显得格外重要,一旦网站出现问题,我们可以利用最新的数据上传到其他空间 ...

  3. 【转载】Wireshark基本介绍和学习TCP三次握手

    Wireshark基本介绍和学习TCP三次握手 转载自:http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html 之前写过一篇博客 ...

  4. ESFramework介绍之(23)―― AgileTcp

    前面已经介绍了ITcp接口,而AgileTcp就是ESFramework给出的ITcp的参考实现.在之前,我曾经讲解过模拟完成端口的Tcp组件实现和异步Tcp组件实现,在它们的基础之上,我更改了处理策 ...

  5. ESFramework介绍之(14)-- AS与FS通信方案

    前面我们已经多次提到,每个AS都有一组FS为之服务(回顾),AS将接收到的功能请求通过Tcp连接池 或Remoting转发给某个FS处理.下面我们将深入讨论AS和FS之间的通信机制. 首先要解决第一个 ...

  6. 项目介绍之论文格式的自动检测与修改系统

    项目背景:此项目隶属于大连理工大学国家级创业训练项目,由三个人负责主要的模块的开发,并交由实验室网站组上线,主要解决高校毕业生论文格式不规范,而人工检查费时费力这一现实问题. 项目内容:此项目的在于检 ...

  7. TCP数据发送之TSO/GSO

    TSO相关的内容充斥着TCP的整个发送过程,弄明白其机制对理解TCP的发送过程至关重要,这篇笔记就来看看TSO相关内容. 1. 基本概念 我们知道,网络设备一次能够传输的最大数据量就是MTU,即IP传 ...

  8. Linux下使用SSH、Crontab、Rsync三工具实现数据自动备份

    Linux下使用SSH.Crontab.Rsync三工具实现数据自动备份 作为网管人员大概都无一例外的经历过系统备份,尤其是重要系统的备份.重要数据库系统的备份工作.由于备份是个频繁而琐碎的工作,如何 ...

  9. ESFramework介绍之(30)―― 消息侦察者 INetMessageSpy

        (本文适用于ESFramework V0.2+) 现在我们回想一下,当网络组件(Tcp/Udp组件)接收到一个消息后,这个消息会流经哪些组件,然后再通过网络组件发送出去了.如果你研究过ESFr ...

最新文章

  1. 第二项目AIaisell(易销宝)
  2. 特征工程 - 特征筛选
  3. MongoDB的学习--聚合
  4. springboot项目文档源码_基于SpringBoot和Vue的企业级中后台项目(附源码)
  5. android7.0 蓝牙定位,BluetoothAdapter在Android6.0/7.0+以上startDiscovery不能发现蓝牙设备问题...
  6. 安装django框架:虚拟环境准备 框架安装
  7. Go 触发 GC 的时机有哪些?能手动触发吗?
  8. 电商BANNER灵感背景欣赏|平面设计中的极简风格
  9. 游戏筑基开发之双链表及其基本功能(C语言)
  10. 2019年英语计算机二级,2019年下半年计算机二级考试时间和英语六级考..._成人英语考试_帮考网...
  11. poj 2253 Frogger floyd 长路求权值最大边,属于简单题!!!!
  12. aqua data studio 连接db2
  13. 添加内核驱动模块(2)(mydriver.c+ Konfig+Makefile )
  14. 工业机器人 郝卫东_基于S3C2410的视觉巡线机器人系统设计
  15. css苹果手机字号变大,css – 智能手机字体大小不一致
  16. word中正文分栏重新换页问题
  17. 项目二--03.基于Nginx、keepalived的高可用集群之keepalived高可用实现
  18. 发明者电子实用宝典_人类发明电话后的第一次通话,竟然是来自发明者的求救声?...
  19. 国风就是帅,会三板吗,看看新天吧
  20. 北京队“接触风波”受罚背后:CBA职业化不断进步

热门文章

  1. 【杂谈】为什么邀请大家加入硬核知识星球有三AI
  2. 有三AI正式跨入2.0,诚邀参与内容创作以及广告须知
  3. TEXT和_T,_TEXT
  4. “盗”亦有道,关于robots协议
  5. 【学习笔记】Sass入门指南
  6. mysql数据库主从配置
  7. JMS学习(五)--ActiveMQ中的消息的持久化和非持久化 以及 持久订阅者 和 非持久订阅者之间的区别与联系...
  8. eclipse中出现Context startup failed due to previous errors错误解决方法
  9. CSS中属性的书写顺序
  10. 怎么还不见2005的中文版出来的?