例子下载地址:http://blog.csdn.net/hujunil/article/details/9923381。java
英文:
linux
This tutorial will walk you through the process of building a MINA based program. This tutorial will walk through building a time server. The following prerequisites are required for this tutorial:web
MINA 2.0.7 Coreapache
JDK 1.5 or greaterapi
[SLF4J|http://www.slf4j.org/] 1.3.0 or greater服务器
Log4J 1.2 users: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.xsession
Log4J 1.3 users: slf4j-api.jar, slf4j-log4j13.jar, and Log4J 1.3.x框架
java.util.logging users: slf4j-api.jar and slf4j-jdk14.jarless
IMPORTANT : Please make sure you are using the right slf4j-*.jar that matches to your logging framework. For instance, slf4j-log4j12.jar and log4j-1.3.x.jar can not be used together, and will malfunction.socket
I have tested this program on both Windows漏 2000 professional and linux. If you have any problems getting this program to work, please do not hesitate to [contact us|Contact] in order to talk to the MINA developers. Also, this tutorial has tried to remain independent of development environments (IDE, editors..etc). This tutorial will work with any environment that you are comfortable with. Compilation commands and steps to execute the program have been removed for brevity. If you need help learning how to either compile of execute java programs, please consult the Java tutorial.
We will begin by creating a file called MinaTimeServer.java. The initial code can be found below: :::Java public class MinaTimeServer {
public static void main(String[] args) { // code will go here next }}
This code should be straightforward to all. We are simply defining a main method that will be used to kick off the program. At this point, we will begin to add the code that will make up our server. First off, we need an object that will be used to listen for incoming connections. Since this program will be TCP/IP based, we will add a SocketAcceptor to our program.
import org.apache.mina.core.service.IoAcceptor;import org.apache.mina.transport.socket.nio.NioSocketAcceptor;public class MinaTimeServer{ public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); }}
With the NioSocketAcceptor class in place, we can go ahead and define the handler class and bind the NioSocketAcceptor to a port.
Next we add a filter to the configuration. This filter will log all information such as newly created sessions, messages received, messages sent, session closed. The next filter is a ProtocolCodecFilter. This filter will translate binary or protocol specific data into message object and vice versa. We use an existing TextLine factory because it will handle text base message for you (you don't have to write the codec part)
import java.nio.charset.Charset;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); }}
At this point, we will define the handler that will be used to service client connections and the requests for the current time. The handler class is a class that must implement the interface IoHandler. For almost all programs that use MINA, this becomes the workhorse of the program, as it services all incoming requests from the clients. For this tutorial, we will extend the class IoHandlerAdapter. This is a class that follows the adapter design pattern which simplifies the amount of code that needs to be written in order to satisfy the requirement of passing in a class that implements the IoHandler interface.
import java.io.IOException;import java.nio.charset.Charset;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); }}
We will now add in the NioSocketAcceptor configuration. This will allow us to make socket-specific settings for the socket that will be used to accept connections from clients.
import java.io.IOException;import java.nio.charset.Charset;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); acceptor.getSessionConfig().setReadBufferSize( 2048 ); acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); }}
There are 2 new lines in the MinaTimeServer class. These methods set the set the IoHandler, input buffer size and the idle property for the sessions. The buffer size will be specified in order to tell the underlying operating system how much room to allocate for incoming data. The second line will specify when to check for idle sessions. In the call to setIdleTime, the first parameter defines what actions to check for when determining if a session is idle, the second parameter defines the length of time in seconds that must occur before a session is deemed to be idle.
The code for the handler is shown below:
import java.util.Date;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IoSession;public class TimeServerHandler extends IoHandlerAdapter{ @Override public void exceptionCaught( IoSession session, Throwable cause ) throws Exception { cause.printStackTrace(); } @Override public void messageReceived( IoSession session, Object message ) throws Exception { String str = message.toString(); if( str.trim().equalsIgnoreCase("quit") ) { session.close(); return; } Date date = new Date(); session.write( date.toString() ); System.out.println("Message written..."); } @Override public void sessionIdle( IoSession session, IdleStatus status ) throws Exception { System.out.println( "IDLE " + session.getIdleCount( status )); }}
The methods used in this class are exceptionCaught, messageReceived and sessionIdle. exceptionCaught should always be defined in a handler to process and exceptions that are raised in the normal course of handling remote connections. If this method is not defined, exceptions may not get properly reported.
The exceptionCaught method will simply print the stack trace of the error and close the session. For most programs, this will be standard practice unless the handler can recover from the exception condition.
The messageReceived method will receive the data from the client and write back to the client the current time. If the message received from the client is the word "quit", then the session will be closed. This method will also print out the current time to the client. 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. If you do not specify a protocol codec, you will most likely receive a IoBuffer object, and be required to write out a IoBuffer object.
The sessionIdle method will be called once a session has remained idle for the amount of time specified in the callacceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );.
All that is left to do is define the socket address that the server will listen on, and actually make the call that will start the server. That code is shown below:
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;public class MinaTimeServer{ private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); acceptor.getSessionConfig().setReadBufferSize( 2048 ); acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); acceptor.bind( new InetSocketAddress(PORT) ); }}
中文:
MINA 2.0.7 Core
JDK 1.5 或更高
SLF4J 1.3.0 或更高
Log4J 1.2 用户: slf4j-api.jar, slf4j-log4j12.jar, 和Log4J 1.2.x
Log4J 1.3 用户: slf4j-api.jar, slf4j-log4j13.jar, 和Log4J 1.3.x
java.util.logging 用户: slf4j-api.jar 和slf4j-jdk14.jar
重要提醒:请确认你使用的slf4j-*.jar
和你的logging框架匹配。举个板栗,slf4j-log4j12.jar 和 log4j-1.3.x.jar 是不能混在一块儿用的,不然会出问题。
We will begin by creating a file called MinaTimeServer.java
咱们建立一个文件名为 MinaTimeServer.java
,文件内容以下:
public class MinaTimeServer{ public static void main( String[] args ) { //尚未东西呢 }}
上面的代码应该不用解释了吧,为了建立咱们的服务,咱们须要一个监听传入链接的对象,因为咱们的项目是基于TCP/IP,因此须要一个SocketAcceptor
对象来帮咱们处理。
import org.apache.mina.core.service.IoAcceptor;import org.apache.mina.transport.socket.nio.NioSocketAcceptor;public class MinaTimeServer{ public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); }}
建立好后,咱们能够定义处理请求的类,和指定监听的端口等。
接下来,咱们须要在配置里添加几个过滤器。第一个是logger
,这个过滤器用来记录全部的信息,好比建立session(会话),接收消息,发送消息,关闭会话等。第二个是ProtocolCodecFilter
(协议编解码过滤器).这个过滤器用来转换二进制或协议的专用数据到消息对象中, 反之亦然。咱们这里使用一个已经存在的TextLine
工厂,由于咱们这里只处理一些文字消息(你不须要再去写编解码部分)。
import java.nio.charset.Charset;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); }}
For this tutorial, we will extend the class IoHandlerAdapter. This is a class that follows the adapter design pattern which simplifies the amount of code that needs to be written in order to satisfy the requirement of passing in a class that implements the IoHandler interface.
接下来咱们须要建立一个handler
来实时处理客户端的链接和请求,这个handler
类必须实现 IoHandler
这个接口。对于全部使用MINA的程序来讲,主要的负荷都在这个文件,它为全部客户端请求提供服务。在这个例子中,咱们将扩展IoHandlerAdapter
类。这是一个听从适配器模式的类,帮咱们简化了不少为了去实现IoHandler
接口的代码。
import java.io.IOException;import java.nio.charset.Charset;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); }}
如今咱们要添加一些NioSocketAcceptor
配置,这将容许咱们设置特殊的socket设置来接收客户端的链接。
import java.io.IOException;import java.nio.charset.Charset;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.service.IoAcceptor;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;public class MinaTimeServer{ public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); acceptor.getSessionConfig().setReadBufferSize( 2048 ); acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); }}
这有两行新代码,这些方法是用来为会话设置IoHandler
,输入缓冲区的大小和空闲等待时间。
须要指定缓冲区大小来告诉底层操做系统为传入的数据分配多少的空间。第二行指定多少时间没有读写操做就进入空闲状态。
handler
的代码以下:
import java.util.Date;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IoSession;public class TimeServerHandler extends IoHandlerAdapter{ @Override public void exceptionCaught( IoSession session, Throwable cause ) throws Exception { cause.printStackTrace(); } @Override public void messageReceived( IoSession session, Object message ) throws Exception { String str = message.toString(); if( str.trim().equalsIgnoreCase("quit") ) { session.close(); return; } Date date = new Date(); session.write( date.toString() ); System.out.println("Message written..."); } @Override public void sessionIdle( IoSession session, IdleStatus status ) throws Exception { System.out.println( "IDLE " + session.getIdleCount( status )); }}
这个类中通常有exceptionCaught
, messageReceived
和 sessionIdle
这几个方法。exceptionCaught
应该老是在handler
中定义,来处理一些异常状况,不然异常信息将没法捕捉。
exceptionCaught
方法简单地打印了错误的堆栈跟踪和关闭会话。对于大多数程序,这将是标准的作法,除非处理程序能够从异常状态中恢复。
messageReceived 方法来处理从客户端接收到的数据,这里是将当前时间返回给客户端,当收到quit
时,会话将被关闭,也会返回一个当前时间给客户端。根据所使用的协议编解码器,object
这个参数传递的类型有所不一样,以及返回的数据时的session.write(Object)
也不一样。若是不指定协议的编解码器,你将收到一个类型为IoBuffer
的对象,返回的数据也要求是IoBuffer
。
The sessionIdle method will be called once a session has remained idle for the amount of time specified in the call acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );.sessionIdle
方法将定时调用一次会话,保持空闲状态。经过调用acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
来设定时间间隔。
全部剩下要作的就是定义套接字地址,该服务器将侦听,实际接入时才会启动服务。
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;public class MinaTimeServer{ private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); acceptor.getSessionConfig().setReadBufferSize( 2048 ); acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); acceptor.bind( new InetSocketAddress(PORT) ); }}
到了这里后,服务端的操做就已经完成了,客户端可参考附件中代码,里面包含了完整的实例,来源自http://blog.csdn.net/hujunil/article/details/9923381。
代码结构
效果
客户端
服务端
源码下载:http://oss.loftor.com/usr/uploads/2014/08/3841585032.rar