MINA2.0 实例--TimeServer
MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个开源Java项目,她是一个Java网络应用程序开发框架,借助她,Java开发者能够简洁的开发出发高性能和高可用的网络应用程序。她依赖于Java NIO,提供了一套便捷操作诸如TCP/IP和UDP/IP等各种传输协议的、抽象的、事件驱动的和异步的API。
Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract ·event-driven · asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.
这个例子来自MINA的官网gettingstarted,也就是Hello级别的例子,本文在其基础上,进一步简化和修改;该实例的运行基础是MINA 2.0.7,MINA 2.*依赖于JDK1.5+,因此JDK版本也要是1.5+,其中引用的jar包有如下两个:mina-core-2.0.7.jar和slf4j-api-1.6.6.jar,mima-core是mina的核心包,她又依赖于slf4j-api,因此,两个包是程序不报错的最低最低的限度,创建一个类(通常也都是创建两个)SimpleTimeServerHandler.java,这里为了更简单,代码如下:
[java]
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class SimpleTimeServerHandler extends IoHandlerAdapter{
@Override
public void messageReceived(IoSession session, Object message){
//服务器端打印出请求的来源
System.out.println("Request From:" + session.getRemoteAddress());
//返给客户端的消息内容:服务器系统当前时间
session.write("Server Time: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
}
public static void main(String[] args) throws IOException{
//创建一个接收器,接收客户端请求
IoAcceptor acceptor = new NioSocketAcceptor();
//Don't know how to handle message of type 'java.lang.String'. Are you missing a protocol encoder?
//编码过滤器,使得服务器可以处理string类型的消息
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
//设置服务器端的处理程序
acceptor.setHandler(new SimpleTimeServerHandler());
acceptor.bind(new InetSocketAddress(60001));
}
}
直接编译执行该类,则启动了服务器,端口是60001。客户端使用最简单的,windows下使用cmd进入控制台(Windows 7默认没有开启该客户端,需要通过“控制面板->程序->程序和功能->打开或关闭Windows功能”,选择“Telnet服务器”和“Telnet客户端”来安装),通过“telnet 127.0.0.1 60001”访问服务器,然后随便输入或者不输入内容,点击回车,即可连接到服务器获取服务器端的时间,而服务器端也可以打印出监控到的客户端的地址;这里可以多开几个cmd窗口,通过telnet进行连接,可以发现不同的窗口对于服务器来说是不同的session。本例在本机和另外一台机器上各开启了一个来进行测试:
客户端的两个:
第一个本机的:
第二个另一台机器:
服务器端打印为:
可以看到服务器端是收到了来自不同的客户端的请求(本机开启两个CMD窗口也可以通过端口号来区分不同的客户端)。
简单解释:
1). 服务器端业务处理者继承IoHandlerAdapter,override其messageReceived(IoSession session, Object message)方法,来完成实际的操作,在本例中做了两家事:第一,在服务器端控制台打印出请求的来源:System.out.println("Request From:" + session.getRemoteAddress()); 第二,给请求的客户端返回系统当前时间:session.write("Server Time: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()))。
2). 服务器启动Main方法做了三件事:创建一个接收器,接收客户端请求;添加编码过滤器,使得服务器可以对特定编码进行处理,本例是对String字符串进行处理,如果不设置这个编码过滤器,则会报错“Don't know how to handle message of type 'java.lang.String'. Are you missing a protocol encoder?”;设置具体的处理程序,即SimpleTimeServerHandler.java,并绑定到相应的监听端口,地址默认是本机的IP。
3). 停止服务器,则客户端窗口会直接“遗失对主机的连接”。
4). 本实例尽量做到最简单化,因此没有开启日志打印,官方的版本(包含在apache-mina-2.0.7-src.zip的“apache-mina-2.0.7\src\mina-example\src\main\java\org\apache\mina\example\gettingstarted\timeserver”中),如下:
除了mina-core-2.0.7.jar和slf4j-api-1.6.6.jar,还需引入slf4j-simple-1.6.6.jar,该jar包是slf4j的默认日志处理包;类包含两个:MinaTimeServer.java和TimeServerHandler.java,分别如下:
[java]
import java.util.Date;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
/**
* The Time Server handler : it return the current date when a message is received,
* or close the session if the "quit" message is received.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class TimeServerHandler extends IoHandlerAdapter
{
/**
* Trap exceptions.
*/
@Override
public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
{
cause.printStackTrace();
}
/**
* If the message is 'quit', we exit by closing the session. Otherwise,
* we return the current date.
*/
@Override
public void messageReceived( IoSession session, Object message ) throws Exception
{
String str = message.toString();
if( str.trim().equalsIgnoreCase("quit") ) {
补充:软件开发 , Java ,