MINA2.0 实例--TimeServer

    MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个开源Java项目,她是一个Java网络应用程序开发框架,借助她,Java开发者能够简洁的开发出发高性能和高可用的网络应用程序。她依赖于Java NIO,提供了一套便捷操作诸如TCP/IP和UDP/IP等各种传输协议的、抽象的、事件驱动的和异步的API。

以下是官网(http://mina.apache.org/)的简介:

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,这里为了更简单,代码如下:

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。本例在本机和另外一台机器上各开启了一个来进行测试:

客户端的两个:

第一个本机的:

MINA2.0 实例--TimeServer_第1张图片

第二个另一台机器:

MINA2.0 实例--TimeServer_第2张图片

服务器端打印为:

MINA2.0 实例--TimeServer_第3张图片

可以看到服务器端是收到了来自不同的客户端的请求(本机开启两个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.jarslf4j-api-1.6.6.jar,还需引入slf4j-simple-1.6.6.jar,该jar包是slf4j的默认日志处理包;类包含两个:MinaTimeServer.java和TimeServerHandler.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") ) {
            // "Quit" ? let's get out ...
            session.close(true);
            return;
        }

        // Send the current date back to the client
        Date date = new Date();
        session.write( date.toString() );
        System.out.println("Message written...");
    }

    /**
     * On idle, we just write a message on the console
     */
    @Override
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
    {
        System.out.println( "IDLE " + session.getIdleCount( status ));
    }
}

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 * A minimal 'time' server, returning the current date. Opening
 * a telnet server, you will get the current date by typing
 * any string followed by a new line.
 * 
 * In order to quit, just send the 'quit' message.
 * 
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public class MinaTimeServer {
    /** We will use a port above 1024 to be able to launch the server with a standard user */
    private static final int PORT = 9123;

    /**
     * The server implementation. It's based on TCP, and uses a logging filter 
     * plus a text line decoder.
     */
    public static void main(String[] args) throws IOException {
        // Create the acceptor
        IoAcceptor acceptor = new NioSocketAcceptor();
        
        // Add two filters : a logger and a codec
        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
   
        // Attach the business logic to the server
        acceptor.setHandler( new TimeServerHandler() );

        // Configurate the buffer size and the iddle time
        acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
        
        // And bind !
        acceptor.bind( new InetSocketAddress(PORT) );
    }
}


基于传统的Socket的实现,可以参见传统Socket实例——TimeServer。

over!

你可能感兴趣的:(MINA2.0 实例--TimeServer)