补充一些可能没讲到的细节。

1.WriteRequest

每一个session.write()操作都会被封装成writeRequest并被添加到WriteRequestQueue队列中。过滤器的每一次责任链流转都是以writeRequest为传参的。我们的老祖父AbstractIoService在实例化时,自带了一个非常重要的属性字段。是不得不注意的参数哟,虽然他对我们基本上是透明的。

[java]  view plain copy
  1. private IoSessionDataStructureFactory sessionDataStructureFactory = new DefaultIoSessionDataStructureFactory();

这个参数就包括了两个鸟不得的结构体,一个就是attribute的map,另一个就是我们可爱的WriteRequestQueue了。

2.IoBuffer

IoBuffer是mina框架对Nio中Buffer的再封装,Buffer应已经是很好用了,mina为什么还要继续封装呢?他给出的原因有2:
  • Buffer没有提供实用的工具型getter和setter方法,比如fill, get/putString, and get/putAsciiInt() 。
  • 原生的Buffer是固定长度的,非常不利于用于操作可变长度的数据。
说实话,这两个原因看上去都不怎么靠谱,要我说,真正的原因就是,框架没有点自己的封装就不是高大上了嘛~哈哈。
mina自身也有点后悔这样的选择,据说在mina3中将采取不同的策略。下面是官方的原话:
This will change in MINA 3. The main reason why MINA has its own wrapper on top of nio ByteBuffer is to have extensible buffers. This was a very bad decision. Buffers are just buffers : a temporary place to store temporary data, before it is used. Many other solutions exist, like defining a wrapper which relies on a list of NIO ByteBuffers, instead of copying the existing buffer to a bigger one just because we want to extend the buffer capacity.
It might also be more comfortable to use an InputStream instead of a byte buffer all along the filters, as it does not imply anything about the nature of the stored data : it can be a byte array, strings, messages...
Last, not least, the current implementation defeat one of the target : zero-copy strategy (ie, once we have read the data from the socket, we want to avoid a copy being done later). As we use extensible byte buffers, we will most certainly copy those data if we have to manage big messages. Assuming that the MINA ByteBuffer is just a wrapper on top of NIO ByteBuffer, this can be a real problem when using direct buffers.

3.用到的设计模式

3.1抽象工厂ProtocolCodecFactory

机智的过滤器ProtocolCodecFilter需要机智的解编码器。以TextLineCodecFactory为例:

3.2 建造者模式

这里的导演类就是我们添加filter的设置代码,而产生出的产品则是顺序不同的filter链。

3.3 适配器模式

mina内部有大量的方法级适配器,如

3.4 装饰者模式

writeRequest这一家子就是很好的例子。

3.5 外观模式

我们劳苦功高的IoServiceListenerSupport,为filter和listener提供了一致性的操作接口

3.6 桥接模式

这就太多了,但凡存在属性字段是接口的,几乎都是桥接模式。只画个类图示意:

3.7 组合模式

过滤器链里面的用到的模式之一。

3.8 享元模式

每个在数组pool里的IoProcessor都是一个享元。

3.9 模板方法

大量的实现都用到了模板方法,这个模式是子类延迟实现的典范。

3.10 观察者模式

在背后默默支持我们的IoServiceListenerSupport,就担负着通知观察者的重任。

3.11 策略模式

每一种filter的具体实现都是一种策略

3.12 责任链模式

在过滤器链中,每个节点都持有对下一个节点的引用。其中节点并非filter实例,而是封装了filter、上一个filter、下一个filter、下一个filter操作对象的Entry对象。

3.13 命令模式

比如session.wirte,发送的消息将被封装到WriteRequest中,最终经过一系列的过滤器被提交到WriteRequestQueue中等待发送。IoProcessor通过轮询将消息队列flush出去。在这里,消息的请求者是session、消息发送实现者是Processor,而消息及消息处理的future被封装到WriteRequest这个对象中。
一般命令模式的主体会持有执行者的引用,命令模式通过调用执行者的方法执行命令,这里是放到一个队列里被轮询执行,所以不能算是完整的命令模式。但命令模式关注的是“行为请求者”和“行为执行者”的解耦,并封装调用请求的变化,这里是符合这个思想的。

4.为什么NioDatagramAcceptor不使用SimpleIoProcessorPool

我们知道在前面讲到NioSocketAcceptor在初始化时会生成SimpleIoProcessorPool的IoProcessor的池,池中每个processor都会处理一组session。而NioDatagramAcceptor没有使用池化的IoProcessor,而是选择实现了IoProcessor,即他本身就是一个IoProcessor,在他自身的executer中只有一个Acceptor勤劳的为他做着接受新数据的
但是为什么呢?
我们知道,UDP是无连接的协议,select()应答器响应有通道的数据到来时,通过receive()方法获取buffer内容。NioDatagramAcceptor只开启了单个DatagramChannel用于数据传输,因为他不需要像NioSocketAcceptor那样维持一个通讯会话session。
对于远程地址相同的请求,NioDatagramAcceptor使用可重用的ExpiringSessionRecycler对象sessionRecycler来复用session。而NioSocketAcceptor会为把每个session分配到指定的IoProcessor池中的一个去处理。
[java]  view plain copy
  1. AbstractPollingConnectionlessIoAcceptor.newSessionWithoutLock( SocketAddress remoteAddress, SocketAddress localAddress ) throws Exception
  2. {
  3. H handle = boundHandles.get( localAddress );
  4. if ( handle == null )
  5. {
  6. throw new IllegalArgumentException( "Unknown local address: " + localAddress );
  7. }
  8. IoSession session;
  9. synchronized ( sessionRecycler )
  10. {
  11. session = sessionRecycler.recycle( remoteAddress );
  12. if ( session != null )
  13. {
  14. return session;
  15. }
  16. // If a new session needs to be created.
  17. S newSession = newSession( this, handle, remoteAddress );
  18. getSessionRecycler().put( newSession );
  19. session = newSession;
  20. }
  21. initSession( session, null, null );
  22. try
  23. {
  24. this.getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
  25. getListeners().fireSessionCreated( session );
  26. }
  27. catch ( Throwable t )
  28. {
  29. ExceptionMonitor.getInstance().exceptionCaught( t );
  30. }
  31. return session;
  32. }

究其原因,应该是NioDatagramAcceptor对于会话的维护不需要付出NioSocketAcceptor那么大的代价。NioDatagramAcceptor只用了一个Selector去监听会话请求,而NioSocketAcceptor用了1个监听连接、CPU+1个去监听不同的session,可见一斑。

结语

客户端的IoConnector部分就不分析了。相信通过这几节的了解,框架结构都非常清楚了。应该没有别的落下= =不过其中有很多对网络的实现方面的细节还不是很清楚,看来要了解网络传输底层的东西才行。

mina学习笔记六:补刀相关推荐

  1. Ethernet/IP 学习笔记六

    Ethernet/IP 学习笔记六 EtherNet/IP defines two primary types of communications: explicit and implicit (Ta ...

  2. 吴恩达《机器学习》学习笔记六——过拟合与正则化

    吴恩达<机器学习>学习笔记六--过拟合与正则化 一. 过拟合问题 1.线性回归过拟合问题 2.逻辑回归过拟合问题 3.过拟合的解决 二. 正则化后的代价函数 1.正则化思想 2.实际使用的 ...

  3. ROS学习笔记六:理解ROS服务和参数

    ROS学习笔记六:理解ROS服务和参数 主要介绍ROS服务和参数,同时使用命令行工具rosservice和rosparam. ROS service service是节点之间互相通信的另一种方式,se ...

  4. opencv 手选roi区域_【opencv学习笔记六】图像的ROI区域选择与复制

    图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...

  5. JS学习笔记六:js中的DOM操作

    1. JS学习笔记六:js中的DOM操作 文章目录 1. JS学习笔记六:js中的DOM操作 1.1. 获取Dom节点 1.2. 元素属性的操作方式 1.3. DOM节点的创建.插入和删除 1.4. ...

  6. Python学习笔记六——画小猪佩奇

    目录 Python学习笔记六--画小猪佩奇 画布 画笔 属性设置 操纵命令 运动命令 画笔控制命令 全局控制命令 其他命令 Python学习笔记六--画小猪佩奇 使用Python的turtle库可以绘 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  8. Polyworks脚本开发学习笔记(六)-比较运算、数学运算、逻辑运算及流程控制

    Polyworks脚本开发学习笔记(六)-比较运算.数学运算.逻辑运算及流程控制 前言 比较运算.逻辑运算及流程控制是编程的基本语法,Polyworks的语法规则与VB/C#/Python等并没有很大 ...

  9. 【K210】K210学习笔记六——MaixHub在线模型训练识别数字

    [K210]K210学习笔记六--MaixHub在线模型训练识别数字 前言 K210准备工作 数据的获取 MaixHub如何在线训练模型 训练模型在K210上的测试 小结 前言 本人大四学生,电赛生涯 ...

最新文章

  1. 突发!美国最大输油管道遭网络攻击关闭!美媒:为其基础设施的脆弱堪忧
  2. Ubuntu配置jdk环境变量
  3. python跟java-还在纠结选Python还是Java?看完就有数了
  4. Hexo错误_FATAL missed comma between flow collection entries at line
  5. WinAPI: Ellipse - 绘制椭圆
  6. C#多线程开发-使用并发集合
  7. Python监听键盘和鼠标事件,并发送内容至邮箱!
  8. bash资源监控_10个资源成为更好的Bash用户
  9. 高等学校计算机房使用章程,普通高等学校设置暂行条例.DOC
  10. ie9 jscript7 内存不足 页面无响应
  11. nyoj 8 一种排序(用vector,sort,不用set)
  12. HP LaserJet 1010 安装方法
  13. BLE_BQB Test_Carrier frequency offset and drift, LE Coded (S=8)_RF-PHY/TRM/BV-14-C
  14. 问题 H: LZY碎大石
  15. 树莓派之火焰传感器模块
  16. 《计算机系统与维护》— CPU的主要技术指标
  17. 单片机关于推挽输出和开漏输出
  18. 使用C#进行图像处理
  19. 物联通信安全需求如何实现
  20. 寒假的时候,小明同学要去拜访很多朋友,恰巧他所有朋友的家都处在坐标平面的X轴上。小明可以任意选择一个朋友的家开始访问,但是每次访问后他都必须回到出发点,然后才能去访问下一个朋友。

热门文章

  1. UI自动化+web测试基础3-2,京东流程
  2. 软件测试都学什么技能?软件测试职业方向在哪里?
  3. 46个健康生活小常识
  4. NLP 中文形近字相似度算法开源实现
  5. 世界上最遥远的距离,不是生与死,而是我心与你心之间的距离。
  6. spring基于5.3.0GA版本-笔记
  7. linux中main数据手册,linux中main()函数中参数来源.doc
  8. 基于java网上租贸系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  9. Java 在线运行编译【运行 Java 代码工具推荐】
  10. Android中的RxJava