您的位置:首页 > 理论基础 > 计算机网络

使用 Apache MINA 开发高性能网络应用程序

2008-08-24 09:27 537 查看
本文将通过一个简单的问候程序HelloServer来介绍MINA的基础架构的同时演示如何使用MINA开发网络应用程序。
ApacheMINA(MultipurposeInfrastructureforNetworkApplications)是Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的MINA版本支持基于JavaNIO技术的TCP/UDP应用程序开发、串口通讯程序(只在最新的预览版中提供),MINA所支持的功能也在进一步的扩展中。

目前正在使用MINA的软件包括有:ApacheDirectoryProject、AsyncWeb、AMQP(AdvancedMessageQueuingProtocol)、RED5Server(MacromediaFlashMediaRTMP)、ObjectRADIUS、Openfire等等。

本文将通过一个简单的问候程序HelloServer来介绍MINA的基础架构的同时演示如何使用MINA开发网络应用程序。

环境准备

首先到官方网站下载最新的MINA版本,地址是:http://mina.apache.org/downloads.html。下载之前先介绍一下MINA的两个版本:1.0.x适合运行环境为JDK1.4,1.1.x适合JDK1.5的版本,两者的编译环境都需要JDK1.5。JDK1.5已经是非常普遍了,本文中使用1.1.5版本的MINA,编译和运行所需的文件是mina-core-1.1.5.jar。
下载MINA的依赖包slf4j。MINA使用此项目作为日志信息的输出,而MINA本身并不附带此项目包,请到http://www.slf4j.org/download.html地址下载slf4j包,slf4j项目解压后有很多的文件,本例中只需要其中的slf4j-api-1.4.3.jar和slf4j-simple-1.4.3.jar这两个jar文件。如果没有这两个文件就会导致启动例子程序的时候报org/slf4j/LoggerFactory类没找到的错误。
当然要求机器上必须装有1.5或者更新版本的JDK。
最好你应该选择一个顺手的Java开发环境例如Eclipse或者NetBeans之类的,可以更方便的编码和调试,虽然我们的最低要求只是一个简单的文本编辑器而已。






编写代码HelloServer.java如下

packagedemo.mina.echo;

importjava.io.IOException;
importjava.net.InetSocketAddress;

importorg.apache.mina.common.*;
importorg.apache.mina.transport.socket.nio.*;
importorg.apache.mina.filter.codec.ProtocolCodecFilter;
importorg.apache.mina.filter.codec.textline.TextLineCodecFactory;

/**
*HelloServer演示程序
*@authorliudong*/
publicclassHelloServer{

privatestaticfinalintPORT=8080;
/**
*@paramargs
*@throwsIOException
*/
publicstaticvoidmain(String[]args)throwsIOException{
IoAcceptoracceptor=newSocketAcceptor();
IoAcceptorConfigconfig=newSocketAcceptorConfig();
DefaultIoFilterChainBuilderchain=config.getFilterChain();
//使用字符串编码
chain.addLast("codec",
newProtocolCodecFilter(newTextLineCodecFactory()));
//启动HelloServer
acceptor.bind(newInetSocketAddress(PORT),newHelloHandler(),config);
System.out.println("HelloServerstartedonport"+PORT);
}
}

/**
*HelloServer的处理逻辑
*@authorliudong
*/
classHelloHandlerextendsIoHandlerAdapter{
/**
*当有异常发生时触发
*/
@Override
publicvoidexceptionCaught(IoSessionssn,Throwablecause){
cause.printStackTrace();
ssn.close();
}

/**
*有新连接时触发
*/
@Override
publicvoidsessionOpened(IoSessionssn)throwsException{
System.out.println("sessionopenfor"+ssn.getRemoteAddress());
}

/**
*连接被关闭时触发
*/
@Override
publicvoidsessionClosed(IoSessionssn)throwsException{
System.out.println("sessionclosedfrom"+ssn.getRemoteAddress());
}

/**
*收到来自客户端的消息
*/
publicvoidmessageReceived(IoSessionssn,Objectmsg)throwsException{
Stringip=ssn.getRemoteAddress().toString();
System.out.println("===>MessageFrom"+ip+":"+msg);
ssn.write("Hello"+msg);
}
}
编译执行

先不用试着去读懂每一行代码的具体意思,用你顺手的编译器编译HelloServer.java,如果报错请确认是否已将前面提到的三个jar文件添加至类路径中。如果一切顺利接着就可以启动HelloServer程序,启动后提示:
HelloServerstartedonport8080
表示启动成功,如果启动失败,问题无外乎是类没找到或者端口占用。如果端口被占用的话,换一个罗,修改
PORT
常量值后再次编译并启动。

测试服务器

打开命令行窗口,输入telnetlocalhost8080后,输入您的英文名或者其他一些乱七八糟的字符后回车再去看看刚启动的服务程序有何反应。我的反应如下:

HelloServerstartedonport8080
sessionopenfor/127.0.0.1:3023
===>MessageFrom/127.0.0.1:3023:hello
===>MessageFrom/127.0.0.1:3023:hello
===>MessageFrom/127.0.0.1:3023:liudong
===>MessageFrom/127.0.0.1:3023:WinterLau
好了,一切正常,恭喜你的第一个使用
MINA
开发的网络程序已经成功运行了。



在介绍架构之前先认识几个接口:

IoAccepter相当于网络应用程序中的服务器端

IoConnector相当于客户端

IoSession当前客户端到服务器端的一个连接实例

IoHandler业务处理逻辑

IoFilter过滤器用于悬接通讯层接口与业务层接口



下图是
MINA
的架构图,



在图中的模块链中,IoService便是应用程序的入口,相当于我们前面代码中的IoAccepter,IoAccepter便是IoService的一个扩展接口。IoService接口可以用来添加多个IoFilter,这些IoFilter符合责任链模式并由IoProcessor线程负责调用。而IoAccepter在ioService接口的基础上还提供绑定某个通讯端口以及取消绑定的接口。在上面的例子中,我们是这样使用IoAccepter的:

IoAcceptoracceptor=newSocketAcceptor();
相当于我们使用了Socket通讯方式作为服务的接入,当前版本的MINA还提供了除SocketAccepter外的基于数据报文通讯的DatagramAccepter以及基于管道通讯的VmPipeAccepter。另外还包括串口通讯接入方式,目前基于串口通讯的接入方式已经在最新测试版的MINA中提供。你也可以自行实现IoService接口来使用自己的通讯方式。

而在上图中最右端也就是IoHandler,这便是业务处理模块。相当于前面例子中的HelloHandler类。在业务处理类中不需要去关心实际的通讯细节,只管处理客户端传输过来的信息即可。编写Handler类就是使用MINA开发网络应用程序的重心所在,相当于MINA已经帮你处理了所有的通讯方面的细节问题。为了简化Handler类,MINA提供了IoHandlerAdapter类,此类仅仅是实现了IoHandler接口,但并不做任何处理。

一个IoHandler接口中具有如下一些方法(摘自MINA的API文档):

voidexceptionCaught(IoSessionsession,Throwablecause)
当接口中其他方法抛出异常未被捕获时触发此方法
voidmessageReceived(IoSessionsession,Objectmessage)
当接收到客户端的请求信息后触发此方法.
voidmessageSent(IoSessionsession,Objectmessage)
当信息已经传送给客户端后触发此方法.
voidsessionClosed(IoSessionsession)
当连接被关闭时触发,例如客户端程序意外退出等等.
voidsessionCreated(IoSessionsession)
当一个新客户端连接后触发此方法.
voidsessionIdle(IoSessionsession,IdleStatusstatus)
当连接空闲时触发此方法.
voidsessionOpened(IoSessionsession)
当连接后打开时触发此方法,一般此方法与sessionCreated会被同时触发
前面我们提到IoService是负责底层通讯接入,而IoHandler是负责业务处理的。那么MINA架构图中的IoFilter作何用途呢?答案是你想作何用途都可以。但是有一个用途却是必须的,那就是作为IoService和IoHandler之间的桥梁。IoHandler接口中最重要的一个方法是messageReceived,这个方法的第二个参数是一个Object型的消息,总所周知,Object是所有Java对象的基础,那到底谁来决定这个消息到底是什么类型呢?答案也就在这个IoFilter中。在前面使用的例子中,我们添加了一个IoFilter是newProtocolCodecFilter(newTextLineCodecFactory()),这个过滤器的作用是将来自客户端输入的信息转换成一行行的文本后传递给IoHandler,因此我们可以在messageReceived中直接将msg对象强制转换成String对象。

而如果我们不提供任何过滤器的话,那么在messageReceived方法中的第二个参数类型就是一个byte的缓冲区,对应的类是org.apache.mina.common.ByteBuffer。虽然你也可以将解析客户端信息放在IoHandler中来做,但这并不是推荐的做法,使原来清晰的模型又模糊起来,变得IoHandler不只是业务处理,还得充当协议解析的任务。

MINA自身带有一些常用的过滤器,例如LoggingFilter(日志记录)、BlackListFilter(黑名单过滤)、CompressionFilter(压缩)、SSLFilter(SSL加密)等。MINA不仅仅是用来开发网络服务器端应用程序,它一样可以使用IoConnector来连接到各种各样的网络服务程序。

通过本文中HelloServer这个例子,我们在惊叹MINA可以带来多么大便利的同时,还不得不为其卓越的性能而骄傲,据称使用MINA开发服务器程序的性能已经逼近使用C/C++语言开发的网络服务。作为MINA的入门文章,性能问题不在本文讨论范围内。

另外在MINA压缩包中附带有不少比HelloServer要好得多的例子,通过这些例子可以进一步的了解并掌握MINA。

http://mina.apache.orgMINA官方网站
http://mina.apache.org/features.html您可以在这里查看关于MINA的更多特性
http://mina.apache.org/testimonials.html看看别人是如何评价MINA的http://asyncweb.safehaus.org/使用MINA开发的高性能WEB服务器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: