MINA Quick Start(1.1)

来源:http://mina.apache.org/quick-start-guide.html

 

这篇介绍带领你浏览基于MINA程序的处理流程。这篇介绍介绍一个时间服务器。在开始前有一些准备工作:

  • MINA1.1核心
  • JDK1.5或更高
  • SLF4J1 .3.0或更高
    •   Log4j 1.2 使用者: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.x
    •   Log4j 1.3 使用者: slf4j-api.jar, slf4j-log4j13.jar, and Log4J 1.3.x
    •   java.util.logging 使用者:slf4j-api.jar and slf4j-jdk14.jar
    •   重要:一定要使用正确的slf4j-*.jar和你使用的log框架版本合适
      如:slf4j-log4j12.jar and log4j-1.3.x.jar 不能再一起使用,否则会失效



我已经测试过这个程序,在Windows2000 professional,和Linux上。如果你有任何问题,请联系我们,这样可以和MINA开发者进行联系。同时,这篇介绍努力和开发平台(IDE、编辑者等)无关。这篇介绍工作环境将使你刚到舒服。为了简洁,Compilation commands and steps to execute the program 被去除了。如果你需要知道如何Compilation commands and steps to execute the program ,参考 Java tutorial

编写MINA时间服务器

 
我们将从 MinaTimeServer.java开始。

public class MinaTimeServer {

    public static void main(String[] args) {
    	// code will go here next
    }
}

 这段代码对任何人都不复杂。我们简单定义了一个main函数,程序的开始。在这一点上,我们将开始增加代码,来搭建我们的服务器。

首先,我们需要一个对象,来监听所有的链接。这个程序是TCP/IP,我们增加一个SockAcceptor

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.transport.socket.nio.SocketAcceptor;

public class MinaTimeServer {

    public static void main(String[] args) {
        // The following two lines change the default buffer type to 'heap',
        // which yields better performance.c
        ByteBuffer.setUseDirectBuffers(false);
        ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

        IoAcceptor acceptor = new SocketAcceptor();
    }
}

 这里的SocketAcceptor,我们能够继续顶一个处理类(handler class),绑定SocketAcceptor到一个端口。如果你对在SocketAcceptor上增加线程模型感兴趣,请阅读Configuring Thread Model

 

我们将要增加SocketAcceptor配置。这允许我们定义socket设置,使用到所有的链接上。

import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class MinaTimeServer {

    private static final int PORT = 9123;

    public static void main(String[] args) throws IOException {
        ByteBuffer.setUseDirectBuffers(false);
        ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

        IoAcceptor acceptor = new SocketAcceptor();

        SocketAcceptorConfig cfg = new SocketAcceptorConfig();
        cfg.getFilterChain().addLast( "logger", new LoggingFilter() );
        cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
    }
}

这里创建了一个SocketAcceptorConfig实例,一旦我们准备好开始启动acceptor,将传给acceptor 。

首先我们重新设置address flag。更多信息见JDK Documentation

其次我们增加一个filter给configuration。这个filter将记录所有信息,如新建一个session,收到信息,传输信息,session关闭。下一个filter是ProtocolCodecFilter。这个filter将解析2进制或者和协议相关的数据转换成对象,或者反过来。

 

最后绑定acceptor到端口。这个方法意味着启动服务器流程。不调用这个方法,服务器不会给客户连接进行服务

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class MinaTimeServer {

    private static final int PORT = 9123;

    public static void main(String[] args) throws IOException {
        ByteBuffer.setUseDirectBuffers(false);
        ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

        IoAcceptor acceptor = new SocketAcceptor();

        SocketAcceptorConfig cfg = new SocketAcceptorConfig();
        cfg.getFilterChain().addLast( "logger", new LoggingFilter() );
        cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));

        acceptor.bind( new InetSocketAddress(PORT), new TimeServerHandler(), cfg);
        System.out.println("MINA Time server started.");
    }
}

定义了一个端口变量,类型为整形的,对SocketAcceptor.bind(SocketAddress, IoHandler)调用 。

第一个参数是SocketAddress,定义了网络地址,需要侦听的。

第二个参数传递的绑定方法是一个类,必须实现IoHandler接口。对已大多数使用MINA的程序,这个成为编程的主要工作(the workhorse of the program),服务于所有的客户端。对于这个介绍,我们将扩张这个IoHandlerAdapter。这个类采用adapter design pattern 来简化需要实现的IoHandler接口的代码编写。

第三个参数是configuration对象。已经配置了一个logger过滤器,编码过滤器。 MINA将每个接收到的消息都经过一些或者全部的过滤器链,在IoAcceptor中定义。这种情况下,我们将传递消息通过logging过滤器,和编码过滤器。这个logging filter将简单的采用SL4J库赖记录log,并且codec过滤器将解码每一个收到的消息,并且采用TextLineCodecFactory对每一个消息进行编码。

import java.util.Date;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.TransportType;
import org.apache.mina.transport.socket.nio.SocketSessionConfig;

public class TimeServerHandler extends IoHandlerAdapter {
	public void exceptionCaught(IoSession session, Throwable t) throws Exception {
		t.printStackTrace();
		session.close();
	}

	public void messageReceived(IoSession session, Object msg) throws Exception {
		String str = msg.toString();
		if( str.trim().equalsIgnoreCase("quit") ) {
			session.close();
			return;
		}

		Date date = new Date();
		session.write( date.toString() );
		System.out.println("Message written...");
	}

	public void sessionCreated(IoSession session) throws Exception {
		System.out.println("Session created...");

		if( session.getTransportType() == TransportType.SOCKET )
			((SocketSessionConfig) session.getConfig() ).setReceiveBufferSize( 2048 );

        session.setIdleTime( IdleStatus.BOTH_IDLE, 10 );
	}
}
 

这里我们有了介绍程序的处理部分代码。我们重写方法:exceptionCaught、messageReceived和sessionCreated。在启动之前,这个类集成了IoHandlerAdapter,实现了Adapter design pattern

 

exceptionCaught:打印错误到strace trace, 关闭连接。对大多数程序,这是一个标准的做法,除非这个handler能够在错误状态中恢复。

 

 

messageReceived:从客户端接收到的数据,会写当前的时间给客户端。如果从客户端接收到的是quit单词,session将会被关闭。这个方法也会打印当前时间给客户端。依赖于你使用的编码,传入的对象(第二个参数)也将不同,如(Depending on the protocol codec that you use, the object (second parameter) that gets passed in to this method will be different, as well as the object that you pass in to the session.write(Object) method. 

如果你没有定义协议编码,你将接收到ByteBuffer对象,且要求协会ByteBuffer对象

 

SessionCreated:session初始化发生的时候。这种情况下,我们打印出方法进入,测试这个链接的传输协议是基于socket的(采用UDP),设置接受buffer大小。上述例子中,传入的bugger尺寸设置成2048字节。空闲时间设置成10秒。如果我们重写sessionidle方法,sessionidle方法将10秒被调用一次。

 

 

Try out the Time server 

At this point, we can go ahead and compile the program.  Once you have compiled the program you can run the program in order to test out what happens.  The easiest way to test the program is to start the program, and then telnet in to the program:

Client Output 
Server Output 
user@myhost:~> telnet 127.0.0.1 9123 
Trying 127.0.0.1... 
Connected to 127.0.0.1. 
Escape character is '^]'. 
hello 
Mon Apr 09 23:42:55 EDT 2007 
quit 
Connection closed by foreign host. 
user@myhost:~>
MINA Time server started. 
Session created... 
Message written...

Using MINA in restricted Java environnements

DIRMINA-659   issue rised the necessity of adding a special permission when running MINA framework in a restricted environnement like applets or Java Webstart technology. This happens when shutting down the thread pools (ExecutorService ).

In order to get it to work properly, you will need to set the following permission :

permission java.lang.RuntimePermission "modifyThread"; 

Or you can also choose to sign your code.

What's Next?

Please visit our  Documentation   page to find out more resources. You can also keep reading  other tutorials .

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值