`

深入理解Apache Mina (1)---- Mina的几个类

阅读更多


最近一直在看Mina的源码,用了Mina这么长时间,说实话,现在才开始对Mina有了一些深刻的理解,关于Mina的基本知识的介绍,这里就不多说了,网上已经有很多不错的文章都对Mina做了较深刻的剖析,现在就是想从Mina的最根本的地方来对Mina做一些深层次上的探讨。

 

还是先从Mina的入口程序来说,每当要启动一个Mina的程序(包括服务器和客户端)时候,这里只是对服务器重点做一些讲解,至于说Mina的客户端的应用,这里只是简单的涉及一点,不会对其做很深入的探讨。但是Mina的服务器和客户端在很大的程度上都是一样,所以这里就“挂一漏万”的简单讲解一下。

 

在此之前我一直想找一种“串糖葫芦”的方式来讲解一下Mina,可是一直没有时间来看Mina的源码,真的是无从下手,虽然网上的很多关于Mina的一些文章,讲解的非常透彻了,但是可能对于初学者来说,显得有些深奥,在这里特别的提一下洞庭散人对Mina源码的透彻的分析,如果你对Mina已经有了一定的了解或者是正在学习Mina的源码,建议你去看看他的博客,里面有很多东西讲的是相当到位的。在这里就不在多举例子了。写这篇文档主要是想对刚接触Mina的人讲解一些Mina的基本知识,由浅入深,一步一步的学习Mina思想的精髓,我接触Mina的时间也比较长了,几乎天天在和它打交道,每当你发现一个新奇的用法的时候,你真的会被Mina所折服,我这里不是对Mina的吹捧,记得我曾经和同事开玩笑说,“等真正的懂得了Mina,你就知道什么叫Java了”,所以,我现在想急切的把现在所知道和了解的所有关于Mina的一些东西都想在这篇文章里面写出来,如果有写的不到位的地方还请各位同学多多指正,下面就开始对Mina做一个完整的介

绍。

 

先说说Mina的几个类和接口
(1) IoService
(2) BaseIoService
(3) BaseIoAcceptor
(4) IoAcceptor
(5) IoConnector

这几个类和接口是整个服务器或客户端程序(IoConnector)的入口程序,其中就Mina的整体上来说,IoService是所有IO通信的入口程序,下面的几个接口和类都是继承或者实现了IoService接口。

 


下面先给出Mina(入口程序)的整体架构图:

                                                                Mina的整体架构图

 

在这里先提出几个个问题:
(1)为什么有了一个IoService还要再有一个BaseIoService?
(2)BaseIoService和IoAcceptor(IoConnector)有什么区别?
(3)BaseIoAcceptor(BaseIoConnector)为什么不去直接实现IoService,而是又添加了

        IoAcceptor(IoConnector)?
   
带着这几个问题我们来解读一下Mina的源码:
首先,解答第一个问题,为什么有了一个IoService还要再有一个BaseIoService?IoService和BaseIoService最明显的区别就是IoService是一个接口,而BaseIoService是一个抽象类。BaseIoService实现了IoService中的部分方法。

 

这里先把IoService接口中要实现的方法和BaseIoService中实现的方法列举如下:

 

通过对IoService和BaseIoService的比较可以发现,除了getDefaultConfig()这个方法没有在BaseIoService中实现之外,其他的方法都已经在BaseIoService实现了。这里就有一个问题,为什么BaseIoService只是实现了IoService的部分方法,而没有全部实现IoService的方法呢?通常都知道,接口中的方法是必须要由实现类来实现的,这点是毋庸置疑的。你可以写一个空方法,里面没有任何的逻辑处理,但是你的实现类中却不能没有该方法。但是在Mina中作为实现类的BaseIoService却没有IoService指定的方法getDefaultConfig(),难道Mina真的有独到之处?不是!仔细看看

BaseIoService你就会知道,BaseIoService是一个抽象类,抽象类就是用来被继承的,它提供了一些其子类公用的一些方法,当抽象类实现一个接口时,抽象类可以有选择性的实现其所有子类都需要的实现的一些方法,对于接口中指定法方法,抽象类可以选择全部实现或者部分实现。在Mina中如果没有BaseIoService这个抽象类,而是由BaseIoAcceptor和BaseIoConnector直接去实现BaseIoService接口,那么必然会导致这个两个实现类中都要重写相应的方法,这样就脱离了面向对象设计的本质,没有达到复用的目的。在BaseIoAcceptor/BaseIoConnector和BaseIoService之间添加一个BaseIoService就是为了达到代码复用的目的。在这个问题上主要是要记住两点:
  
   1)抽象类在实现接口的时候可以部分或者全部实现接口中的方法。但是当抽象类只是实 
       现了接口中的部分方法的时候,抽象类的子类必须要实现抽象类中未实现的接口的方
       法。在此处,IoService的getDefaultConfig()方法在BaseIoService(BaseIoAcceptor  
       是BaseIoService的子类,但它也是一个抽象类,所以它也没有实现getDefaultConfig()),

       getDefaultConfig() 是    由BaseIoAcceptor的子类们来实现的(如SocketAcceptor,这是一个

       具体实现类)。所以接口的所有方法必须被具体的实现类实现和抽象类在实现接口的时候可以部分

       或者全部实现接口中的方法是不矛盾的。

 

   2)注意代码的重用。在面向对象的编程语言中都提供了抽象类和接口,抽象类和接口最大的区别

        就是抽象类提供了方法的具体实现,供其子类来调用;而接口只是提供了对方法的声明,其方

        法的实现要由其具体实现类来做。在Java中一个子类只能有一个父类,但是却能实现多个接口。

       个人认为接口和抽象类各有特色,接口的使用比较灵活,不同的接口可以让其子类扮演不同的角

       色,侧重于类的复用,在很大程度上解决了代码复用的问题;抽象类更侧重的是方法的复用,某

       种意义上讲,抽象类的使用对于程序来说使用起来更加轻松,但是是使用抽象类还是接口要根据

       具体的情况而定。


      对于接口和抽象类的具体的用法请参考闫宏的《Java与模式》中相关部分的讲解。

 

之所以在这里罗列这么些问题,目的不仅仅是为了讲解Mina的原理,而是想从一个高的角度来看待的这个经典的开源项目,通过对Mina的学习和理解,能够真正的懂得什么是一个项目,什么是面向对象编程,更本质的东西是怎么灵活运用Java来达到上面的两个目的。这个才是最重要的,哪怕是你在看完本文后对Mina的理解还是有点模糊,但是你至少要知道在编写一个程序的时候怎样从面向对象的角度上去思考一个问题,而不是在用着面向对象的语言写着结构化的程序。这些东西都是自己做开发这么长时间的一些心得,在这里总结出来,目的主要是用于交流和学习,不是在卖弄,只是想让更多的初学者少走一些弯路,懂得学习的方法。

 

还是回到对Mina的刚提出的那几个问题上来,现在,第一个问题已经解决了,为什么有了一个IoService还要再有一个BaseIoService?答案就是为了代码的复用。

 

其次,下面开始讨论第二个问题,BaseIoService和IoAcceptor(IoConnector)有什么区别?
在讨论这个问题之前,还是先给出这两个类(接口)提供的方法,如下图:

 

在讨论第一个问题的时候我们已经看过了BaseIoService的方法了,但是没有对这些方法的功能做些梳理,现在就对这些方法做些简单的介绍:

 

getFilterChainBuilder()和setFilterChainBuilder():这两个方法主要是对一个服务的IoFilter的操作,关于IoFilter的详细介绍会在后面给出,现在你可以将其理解为是一个处理业务逻辑的模块,例如:黑名单的处理、数据的转换、日志信息的处理等等都可以在这个IoFilter中实现,它的工作原理和Servlet中的过滤器很相似。

 

addListener()和removeListener():这两个方法通过名字看就可以理解了,就是给当前的服务添加和删除一个监听器,这个监听器主要是用于对当前连接到服务的IoSession进行管理,这个也会在后面做详细的讲解。

 

getManagerServiceAddress()和getManagerSessions():这两个方法的功能比较相似,一个是获取当前服务所管理的远程地址,一个是获取当前服务所管理的会话IoSession,IoSession对SocketAddress做了一个完整的封装,你也

可以先将这两个方法的功能理解为是一回事,具体的区别会在后面给出。isManaged():检测某个SocketAddress是否处于被管理的状态。

 

getListeners():获取当前服务的监听器。

 

看了上面对BaseIoService功能的介绍,现在我们可以理解BaseIoService提供的方法主要是用于对当前服务的管理。那么要管理一个服务,前提条件是这个服务必须存在,存在的前提是什么,就是要启动一个服务,或者是连接到一个远程主机上,这两个任务分别是IoAcceptor和IoConnector来完成的,此处要注意的是这两个对象都是接口,没有具体的实现,具体的实现会由下面介绍的它们相关的子类(SocketAcceptor等)来实现。这样IoAcceptor/IoConnector的功能我们就可以总结出来了,就是启动和停止一个服务。

 

对于一个完整的服务来说,既要有启动这样的前提条件,还要有对服务的管理和对服务响应的逻辑处理,这两个缺一不可,回到第二个问题,BaseIoService和IoAcceptor(IoConnector)有什么区别?区别就在于它们实现的功能不一样,但都是为了一个完整的服务来打基础的,两者缺一都不能称为一个完整的服务。这三个都是IoService子类(子接口),oService只是提供了一些服务应该具有多基本的方法,BaseIoService提供了IoService部分方法的具体实现,而IoAcceptor(IoConnector)是对特定服务要具备的操作的做了一些扩展,这样一个服务完整的模型正在逐渐向我们清晰的展现出来。

 

再次,讨论一下第三个问题。BaseIoAcceptor(BaseIoConnector)为什么不去直接实现IoService,而是又添加了IoAcceptor(IoConnector)?这个问题其实在上面已经有所涉及,为了达到对象复用的目的,所以Mina的设计者给出了一个BaseIoService,IoAcceptor(IoConnector)是实现一个特定服务必须要提供的一些方法。更具体一点,IoAcceptor(IoConnector)是为了一个特定的服务(服务器/客户端)而设计的,而IoService只是提供了一个服务应该具备的一些基本的方法。所以在Mina中给出了一个针对具体服务的一个接口IoAcceptor(IoConnector),这样BaseIoAcceptor(BaseIoConnector)就提供了一个服务所必备的一些条件。因为它即实现了IoAcceptor(IoConnector)接口又继承了抽象类BaseIoService,这样就实现了IoService中的所有方法,并且也添加了特定服务应该具有的方法(即IoAcceptor(IoConnector)中的方法)。以上就是第三个问题的答案。

 

 

 

Mina中提供的几个特定的服务
从上面的讨论中我们已经知道了Mina上层的类和接口的一些功能。即图中所示的已经在上面解释清楚了。


 在此我们可以把Mina的上层结构简单的定义为Mina的“抽象层”,既然有了抽象层,肯定就会有其具体实现,抽象中最重要的两个类是BaseIoAcceptor和BaseIoConnector,它们分别是用于服务器和客户端的一个入口程序。

首先,说一下BaseIoAcceptor中的三个具体实现类:


DatagramAcceptorDelegate:数据报UDP通信的服务器入口程序。该类使用UDP协   议进行通信,UDP协议主要是用在视频、远程服务的监听(如心跳程序)中等数据传输   要求不是很高的地方。
VmPipeAcceptor:虚拟通道(VM)通信的服务器入口程序。虚拟管道协议主要用于无线通信方面。             
SocketAcceptor:TCP/IP通信的服务器入口程序。这个是比较常用的协议,该协议主要   数据传输要求较高的地方,比如实时系统、游戏服务器等。

BaseIoAcceptor及其子类
与BaseIoAcceptor相对应的就是BaseIoConnector,该类主要用于客户端程序。其具体的子类就不再赘述,这里只给出BaseIoConnector及其子类的结构图。

BaseIoConnector及其子类

关于SocketAcceptor、IoFilter、IoProcessor、IoHandler等会有专门的文章来讨论。这里就不在对这些组件类做详细的说明了。


分享到:
评论
17 楼 tantan 2012-03-12  
mina 多并发实时传输,
只能建立一个连接传输,如何解决呢
acceptor = new NioSocketAcceptor();
//
// 加入过滤链编码和解码的构建对象
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new CodecFactory()));// new
// CodecFactory()
// 待处理客户端连接建立、数据包接受,数据包发送....
acceptor.setHandler(new PVServerHandler(PacketProcessor.getInstance()));
try {
acceptor.bind(new InetSocketAddress(config.getPort()));
System.out.println("监听端口: " + config.getPort());
} catch (Exception e) {
System.out.println("监听端口: " + config.getPort() + "失败"
+ e.getMessage());
return ;
}
16 楼 ChinaEstone 2010-12-17  
Mybeautiful 写道
请教一下,
Mina2.0中,这个方法不见了
IoAcceptor.isManaged

有相应替换的方法吗?


试试2.0中的IoAcceptor.getManagedSessions(),然后用Map类提供的方法检查下
某个session是否被管理。
Map<Long,IoSession> managedSessions = ioacceptor.getManagedSessions();
managedSessions.isContainsValue(IoSession)试试。
15 楼 Mybeautiful 2010-12-16  
请教一下,
Mina2.0中,这个方法不见了
IoAcceptor.isManaged

有相应替换的方法吗?
14 楼 ChinaEstone 2009-10-23  
BaseIoServic
wy19280469 写道
在BaseIoAcceptor/BaseIoConnector和BaseIoService之间添加一个BaseIoService就是为了达到代码复用的目的

2个相同的BaseIoService?


除了用到接口和抽象类的复用特性外,我没看出来Mina这样写还有其他什么目的,你如果有所发现,请指教。
13 楼 doyourbest 2009-10-23  
没有
ChinaEstone 写道
doyourbest 写道
建议LZ使用mina2.0
采用nio方式与普通io方式,性能差别很大


能说的具体一点吗?我没有明白你的说的是什么意思!
你是不是说Mina 1.1.7使用的不是JAVA NIO?



没有详细看Mina1.0源码,SocketConnector 这些Class Name(在Mina2.0中,都以NioXXXXX开头),我误以为使用的普通Socket链接方式。

个人你感觉2.0与1.0最明显变化除了线程模型,就是IoBuffer,终于回归正途了。
12 楼 wy19280469 2009-10-23  
在BaseIoAcceptor/BaseIoConnector和BaseIoService之间添加一个BaseIoService就是为了达到代码复用的目的

2个相同的BaseIoService?
11 楼 ChinaEstone 2009-10-15  
ha397666 写道
楼主! 您是造福菜鸟的圣人啊! 谢谢!


过奖了,呵呵,我只是把自己知道的一点可怜的知识拿来给大家分享一下,呵呵。
10 楼 ha397666 2009-10-15  
楼主! 您是造福菜鸟的圣人啊! 谢谢!
9 楼 ChinaEstone 2009-10-15  
doyourbest 写道
建议LZ使用mina2.0
采用nio方式与普通io方式,性能差别很大


能说的具体一点吗?我没有明白你的说的是什么意思!
你是不是说Mina 1.1.7使用的不是JAVA NIO?
8 楼 doyourbest 2009-10-14  
建议LZ使用mina2.0
采用nio方式与普通io方式,性能差别很大
7 楼 cnng_marjory 2009-09-24  
经典啊 !!
6 楼 lujiawu12 2009-08-23  
很到位   谢谢伟大的楼主了 
5 楼 Leilei2541 2009-08-10  
楼主,多发点,讲的真的很好
4 楼 ChinaEstone 2009-08-05  
east_java 写道
LZ用的是什么版本啊。。有些类现在都没有了。

Apache Mina 1.1.7,该版本是JDK 5以上的稳定版本。
3 楼 east_java 2009-08-05  
LZ用的是什么版本啊。。有些类现在都没有了。
2 楼 qipei 2009-08-02  
学习中。。
正在实现 联通的SGIP协议
正需要呢。。。
1 楼 ChinaEstone 2009-07-29  
附件中有本文的完整内容,欢迎下载!

相关推荐

    深入理解Apache_Mina_(1)----_Mina的几个类

    深入理解Apache_Mina_(1)----_Mina的几个类深入理解Apache_Mina_(1)----_Mina的几个类深入理解Apache_Mina_(1)----_Mina的几个类

    关于apache Mina Server

    深入理解Apache_Mina_(1)----_Mina的几个类 深入理解Apache_Mina_(2)----_与IoFilter相关的几个类 深入理解Apache_Mina_(3)----_与IoHandler相关的几个类 深入理解Apache_Mina_(4)----_IoFilter和IoHandler的区别和...

    深入理解Apache Mina (3)---- 与IoHandler相关的几个类

    NULL 博文链接:https://chinaestone.iteye.com/blog/424576

    深入理解Apache Mina (2)---- 与IoFilter相关的几个类

    NULL 博文链接:https://chinaestone.iteye.com/blog/424568

    深入理解Apache_Mina

    Java Nio ByteBuffer与Mina ByteBuffer的区别 Mina的几个类 与IoFilter相关的几个类 与IoHandler相关的几个类 IoFilter和IoHandler的区别和联系 配置Mina的线程模型

    mina传输中用到的包

    在apache mina传输中可能需要的几个jar包,包括 mina-core-2.0.0-M1.jar slf4j-api-1.5.11.jar slf4j-log4j12-1.5.11.jar log4j-1.2.14.jar

    mina:使用Apache MINA在Java中进行分布式并行计算

    这使用Apache Mina库和Guava FutureCallbacks实现了分布式计算范例。 您可以启动通过TCP将工作分派到多个远程客户端的服务器。 您可以指定每个客户一次可以并行处理多少个工作单元。 如果客户去世,工作将自动重新...

    Mina2.0框架源码剖析

    整个框架最核心的几个包是:org.apache.mina.core.service, org.apache.mina.core.session, org.apache.mina.core.polling以及org.apache.mina.transport.socket。

    java开源包1

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    test-net-frameworks

    在查阅了几个、文章和/ 测试后,结果发现当今主要的竞争库是 Netty 和 MINA。 我尝试通过编写简单的服务器来使用每一个: 使用 Netty,实现了一个服务器,它接收消息并将其发送到所有连接的客户端。 使用 Apache...

    java开源包10

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包11

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包2

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包3

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包6

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包5

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包4

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包8

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包7

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包9

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

Global site tag (gtag.js) - Google Analytics