一、简介:

Apache Mina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步 IO 默认使用的是 JAVA NIO 作为底层支持)操作的编程模型。

二、使用示例:

三、体系结构:

1. IoService

负责具体的IO相关工作。IOService的意义在于隐藏底层IO的细节,对上提供统一的基于事件的异步IO接口。每当有数据到达时,IOService会先调用底层IO接口读取数据,封装成IoBuffer,之后以事件的形式通知上层代码;从图上看,进来的low-level IO经过IOService层后变成IO Event。

在服务端的接口是IoAcceptor,具体实现类是NioSocketAcceptor,对应客户端的接口是IoConnector,实现类是NioSocketConnector;

2. IoFilterChain

Mina的设计理念之一就是业务代码和数据包处理代码分离,业务代码只专注于业务逻辑,其他的逻辑如:数据包的解析,封装,过滤等则交由IoFilterChain来处理。开发者通过往Chain中添加IoFilter,来增强处理流程,而不会影响后面的业务逻辑代码。

3. IoHandler

实现业务逻辑的地方,需要有开发者自己来实现这个接口;对于Server端和Client端来说都是IoHandler接口的实现类;在Mina中提供了IoHandler的实现类IoHandlerAdapter,业务逻辑代码类只需要继承这个类即可;

4. IoSession

一个IoSession对应于一个底层的IO连接,通过IoSession,可以获取当前连接相关的上下文信息,以及向远程peer发送数据。发送数据其实也是个异步的过程。发送的操作首先会逆向穿过IoFilterChain,到达IoService。但IoService上并不会直接调用底层IO接口来将数据发送出去,而是会将该次调用封装成一个WriteRequest,放入session的writeRequestQueue中,最后由IoProcessor线程统一调度flush出去。所以发送操作并不会引起上层调用线程的阻塞。

四、源码分析:

(一)服务端Service结构图:

1、IoService接口负责具体的IO相关工作。IOService的意义在于隐藏底层IO的细节,对上提供统一的基于事件的异步IO接口,并且接收客户端的连接并处理的组件;

2、AbstractIoService实现了IoService接口,作为服务端的抽象服务类,executeor作为Acceptor线程类执行的线程池(Acceptor线程用于监听端口、接收客户端连接、创建Session并交由Processor来处理);handler保存了用户业务逻辑处理的对象,过滤链的最后一个过滤器就是指向这个handler来处理的;sessionConfig表示session的配置信息,这个类用于所有session的初始配置信息,每当有客户端连接进来创建session时,就用这个配置来初始化session的配置信息;

3、AbstractIoAcceptor派生自AbstractIoService类,提供的defaultLocalAddresses用于绑定端口进行监听的;

4、AbstractPollingIoAcceptor派生自AbstractIoAcceptor,里面有一个Processor的池子,每一个session的业务处理都会交给其中一个Processor来处理;

5、NioSocketAcceptor派生自AbstractPollingIoAcceptor,selector表示NIO的选择器,这个类里面主要实现了服务端口的绑定、打开channel、打开选择器、注册选择器到channel上、监听等待客户端连接等操作;

(二)初始化NioSocketAcceptor流程:

1、代码new一个NioSocketAcceptor对象,NioSocketAcceptor的构造函数交给父类AbstractPoolingIoAcceptor,AbstractPoolingIoAcceptor的构造函数首先创建SimpleIoProcessorPool的处理器池对象;

2、SimpleIoProcessorPool是一个IoProcessor的池子,每个IoProcessor执行时又都是一个线程对象,需要一个线程池来调度这些线程,因此SimpleIoProcessorPool的构造函数会首先判断是否从外面传递了线程池executor对象进来,如果没传则创建新的线程池对象(newCachedThreadPool);接下来会创建cpu核数+1个IoProcessor对象放置到处理器池中;

3、处理器池创建完成后就会调用NioSocketAcceptor.Init方法来完成初始化,init方法中只是调用Selector.open来打开选择器;

4、AbstractPoolingIoAcceptor创建完成并返回后,NioSocketAcceptor调用DefaultSocketSessionConfig.init来完成Session的配置的默认初始化;最后返回创建完成的NioSocketAcceptor对象给创建者;

(三)绑定端口并接收客户端连接流程:

1、客户端调用NioSocketAcceptor.bind在服务器绑定指定端口,这个bind会传递给父类AbstractIoAcceptor.bind来处理,然后他又调用子类AbstractPoolingIoAcceptor.bindInternal来处理,在这里创建Acceptor线程对象并交由线程池对象executor来执行;

2、Acceptor线程里面首先调用selector.select()打开选择器,然后调用ServerSocketChannel.open打开服务端channel,设置channel的相关属性(比如非阻塞configureBlocking、ReuseAddress等),ServerSocket.bind绑定端口监听,在channel上注册选择器Selector;

3、上面的 NIO初始化操作完成后,最后调用ServerSocketChannel.accept()等待客户端连接,此时线程会阻塞,到这里服务端的绑定操作完成;

4、当有客户端连接请求到达时,上面的accept阻塞会返回,然后根据与客户端连接的socketChannel创建NioSocketSession对象并初始化这个session(NioSocketSession对象会关联AbstractPollingIoAcceptor的ProcessorPool对象,这个ProcessorPool是在构造函数里面传入的);

5、接下来会根据session来选择对应的Processor对象(选择的方法是拿sessionId对ProcessorPool的个数取余作为下标,然后用这个下标到ProcessorPool里面去取Processor对象),然后将该session添加到Processor要处理的session列表里面(processor对象里面维护着一个session队列——newSessions变量);

6、最后调用startupProcessor方法来处理该Processor对象管理的session请求;

(四)处理客户端请求(startupProcessor)流程:

1、startupProcessor创建内部Processor线程对象并交由线程池对象executor执行,首先selector.select阻塞到有事件就绪才继续往下执行;

2、循环遍历processor管理的所有session,给session注册OP_READ事件,构造session的过滤链FilterChain;

3、然后在channel上读取数据到buffer,最后调用filterChain.fireMessageReceived将接收到的消息经过过滤链传递给业务逻辑处理handler来处理,如果发生异常,则调用filterChain.fireExceptionCaught经由过滤链传递给业务逻辑处理handler来处理异常;同样write方法与Read类似,只是在经过过滤器链时的顺序是相反的;

mina学习总结的更多相关文章

  1. MINA学习汇总

    MINA学习汇总 Apache Mina Server 是一个网络通信应用框架,用于开发高性能和高可用性的网络应用程序.它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(然,也可以提供JAVA ...

  2. mina学习(一)

    Mina:是一个帮助用户开发高性能和高伸缩性网络应用程序的框架 学习地址链接:http://www.cnblogs.com/xuekyo/archive/2013/03/06/2945826.html ...

  3. 【MINA学习笔记】—— 1.体系结构分析[z]

    前言 Apache的MINA框架是一个早年非常流行的NIO框架,它出自于Netty之父Trustin Lee大神之手.虽然目前市场份额已经逐渐被Netty取代了,但是其作为NIO初学者入门学习框架是非 ...

  4. Mina学习之---mina整体流程介绍

    现在公司使用的NIO框架一直时候Mina,当然这也的框架还有Netty.虽然一直在用,但只是简单的停留在业务层面,最近面试的时候有问Mina相关的东西.在之前的博客中已经对BIO,NIO,AIO这三种 ...

  5. NIO框架Mina学习

    前言: 找了篇文章看了看,nio框架数Mina用的最多! 代码: 服务端: package com.mina; import java.net.InetSocketAddress; import ja ...

  6. mina学习

    长连接表示一旦建立了链接,就可以长时间的保持双方的通讯,例如: socket链接,推送平台. 短链接表示建立链接,完成数据的交换之后,就断开链接,例如: http链接. mina 框架是对socket ...

  7. Mina学习之IoFilter

    IoFilter 是MINA中的一个核心结构,扮演了非常重要的角色.IoFilter在IoService和IoHandler过滤了所有的I/O 事件和请求.如果你有做个web项目的经验,则很类似于we ...

  8. Mina学习之IoSession

    Session(会话)是Mina的核心部分:每当一个clinent连接到server时,都会创建一个新的session,并且保存在内存中知道该链接断开. session 是用来存储一些关于连接信息,加 ...

  9. MINA学习之IoService

    从上一篇文章中知道,IoService出于MINA体系中的底层.IoService将会帮你维护网络交互,接受消息,发送消息,管理Sessions,管理连接Connections等等. IoServic ...

  10. MINA学习之体系介绍

    基于MINA应用程序结构图: 我们可以看出,MINA是应用程序(客户端或服务端)和底层基于TCP,UDP等通讯协议的网络层之间的粘合剂.而且各个模块之间是相互独立的,你只需要在MINA体 系基础上设计 ...

随机推荐

  1. 解决无法创建 JPA 工程的问题

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7703803.html ------------------------------------ ...

  2. 从Oracle数据库中的本地命名文件tnsnames.ora来看服务别名、服务名和实例名的区别。

    tnsnames.ora的作用这里就不多述了,各位应该都知道. 首先先看两个例子: test1 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCO ...

  3. <context:annotation-config/>和<mvc:annotation-driven/>及解决No mapping found for HTTP request with URI [/role/getRole] in DispatcherServlet with name 'springmvc-config'

    1:什么时候使用<context:annotation-config> 当你使用@Autowired,@Required,@Resource,@PostConstruct,@PreDest ...

  4. Day7作业及默写

    1. 判断一个数是否是水仙花数, 水仙花数是一个三位数, 三位数的每一位的三次方的和还等于这个数. 那这个数就是一个水仙花数. 例如: 153 = 1**3 + 5**3 + 3**3 InputNu ...

  5. Python 函数的嵌套

    # 函数的互相调用 def func1(): print("我是神器的func1") def func2(): func1() print("我是神器的func2&quo ...

  6. Centos7 使用Docker搭建Oracle测试环境

    1.更新yum yum update 2.安装Docker yum install docker 安装完成后查看Docker的版本: docker version 查看Docker的信息: docke ...

  7. Semaphore计数信号量

    ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semp = new Semaphore(5); for ...

  8. 【转】C++类内存分布

    C++类内存分布  https://www.cnblogs.com/jerry19880126/p/3616999.html 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看 ...

  9. CNN 参数计算

    CNN 时间计算复杂度与空间复杂度 即,连续个数与参数个数, 每一个连接都意味着一个计算, 每一个参数都意味一个存储单元. 只计算主要部分. CNN局部连接与权值共享 如图所示: 全连接:如左图所示, ...

  10. django配置Ueditor富文本编辑器

    1.https://github.com/twz915/DjangoUeditor3下载包,进入包文件夹,找到DjangoUeditor包拷贝到项目下,和xadmin同级目录 2.找到项目的setti ...