Apache Mina的学习应用


在一般的项目中使用Mina要求在发送消息前加密数据,在接收数据时解析数据。在加密和解析需要自己定义相应的解析协议。如果采用Mina是就可以简单省事的定义自己的解析和加密协议。 只需实现Mina自己的类库即可。实现相应的方法即可。

   如在客户端发送消息先加密,在服务端进行解密,服务端把执行的结果封装成对象之后,先加密之后发送到客户端,客户端,接收到信息后在解密的过程,也是多数mina应用的过程。

 

  首先定义自己的协议基类:

自定义消息体必须是实现MINA的消息的加密类MessageEncoder类 和消息的解密类:MessageDecoder 类

 

 

针对客户端消息Message 和ResultMessage 的不同解析过程主要为消息体的解析。

在消息的加密和解密基类中定义一些公共 的方法。

 

 

消息的加密类的基类:

 package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.apache.mina.filter.codec.demux.MessageEncoder;
import cn.com.unutrip.java.opensource.mina.sumup.message.AbstractMessage;
/**
 * 加密消息头和消息的体的信息
 * @author longgangbai
 *
 * @param <T>
 */
public abstract class AbstractMessageEncoder<T extends AbstractMessage> implements MessageEncoder<T> {
      private final int type;
      protected AbstractMessageEncoder(int type){
    this.type=type;
      }
      
      /**
       * 加密的整个过程的
       */
      @Override
      public void encode(IoSession session ,T message ,ProtocolEncoderOutput out)throws Exception
      {
   IoBuffer buf=IoBuffer.allocate(6);
          //Enable auto-expand for easier encoding
   buf.setAutoExpand(true);
   //加密 消息头
   buf.putShort((short)type);
   buf.putInt(message.getSequence());
   //加密消息体
   encodeBody(session, message, buf);
          buf.flip();
          out.write(buf);
      }
      /**
       * 解析消息的体的方法的
       * @param session
       * @param message
       * @param out
       */
      protected abstract void encodeBody(IoSession session ,T message ,IoBuffer out);
}

消息的解密类的基类:

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.demux.MessageDecoder;
import org.apache.mina.filter.codec.demux.MessageDecoderResult;
import cn.com.unutrip.java.opensource.mina.sumup.message.AbstractMessage;
/**
 * 
 * @author longgangbai
 *
 */
public abstract class AbstractMessageDecoder implements MessageDecoder{
     private final int type;
     private int sequence;
     private boolean readHeader;
 
     protected AbstractMessageDecoder(int type){
         this.type=type;
     }
     public MessageDecoderResult decodable(IoSession session ,IoBuffer in)
     { 
  //当信息头(header)中没有读取时返回需要读取 NEED_DATA
         if(in.remaining()<Constants.HEADER_LEN){
              return MessageDecoderResult.NEED_DATA;
         }
         //如果类型和长度匹配返回 OK
         if(type==in.getShort())
         {
            return  MessageDecoderResult.OK;
         }
         //如果不匹配返回NOT OK
        return MessageDecoderResult.NOT_OK;  
     }
     
     
     public MessageDecoderResult decode(IoSession session ,IoBuffer in,ProtocolDecoderOutput out)throws Exception
     { 
  //当信息头(header)中没有读取时返回需要读取 NEED_DATA
         if(!readHeader){
             //忽略此种类型
             in.getShort();
             sequence=in.getInt();
             readHeader=true;
         }
         // 获取消息的解析内容
         AbstractMessage m=decodeBody(session, in);
         //如果
         if(m==null)
         {
            return  MessageDecoderResult.NEED_DATA;
         }else{
             //重新设置readerHeader 为下一次解析作准备
             readHeader=false;
         }
         m.setSequence(sequence);
         out.write(m);
        return MessageDecoderResult.OK;  
     }
     /**
      * 解析消息的body体的信息
      * @param session
      * @param in
      * @return
      */
     protected abstract AbstractMessage decodeBody(IoSession session ,IoBuffer in);
}

Message消息体的加密和解密过程:

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import cn.com.unutrip.java.opensource.mina.sumup.message.AbstractMessage;
import cn.com.unutrip.java.opensource.mina.sumup.message.AddMessage;
/**
 * 添加消息的解密解析器
 * @author longgangbai
 *
 */
public class AddMessageDecoder extends AbstractMessageDecoder {
    public AddMessageDecoder(){
  super(Constants.ADD);
    }
    /**
     * 解析消息体的过程
     */
    @Override
    protected AbstractMessage decodeBody(IoSession session, IoBuffer in) {
         if(in.remaining()<Constants.ADD_BODY_LEN)
         {
             return null;
         }
         AddMessage message=new AddMessage();
         message.setValue(in.getInt());
 return message;
    }
    /**
     * 解析完毕的操作
     */
    @Override
    public void finishDecode(IoSession session, ProtocolDecoderOutput output)
     throws Exception {
    }
}

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import cn.com.unutrip.java.opensource.mina.sumup.message.AddMessage;
/**
 *  添加消息的加密解析器
 * @author longgangbai
 *
 * @param <T>
 */
public  class AddMessageEncoder<T extends AddMessage> extends AbstractMessageEncoder<T> {
         public AddMessageEncoder() {
             super(Constants.ADD);
        }
 @Override
 protected void encodeBody(IoSession session, T message, IoBuffer out) {
     out.putInt(message.getValue());
 }
 public  void dispose()throws Exception{
             
        }
}

在注册自定义协议的工厂的实现类:通过继承MINA的 DemuxingProtocolCodecFactory实现自定义协议的编码的类。

消息结果的:

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import cn.com.unutrip.java.opensource.mina.sumup.message.AbstractMessage;
import cn.com.unutrip.java.opensource.mina.sumup.message.ResultMessage;
import static cn.com.unutrip.java.opensource.mina.sumup.codec.Constants.RESULT;
import static cn.com.unutrip.java.opensource.mina.sumup.codec.Constants.RESULT_CODE_LEN;
/**
 * 
 * @author longgangbai
 *
 */
public class ResultMessageDecoder extends AbstractMessageDecoder{
     private  int code;
     private boolean readCode;
 
     public ResultMessageDecoder(){
         super(Constants.RESULT);
     }
     /**
      * 解析消息的body体的信息
      * @param session
      * @param in
      * @return
      */
     protected  AbstractMessage decodeBody(IoSession session ,IoBuffer in)
     {
   if(!readCode)
   {
      if(in.remaining()<RESULT)
      {
   return null;
      }    
      code=in.getShort();
      readCode=true;
   }
   if(code==Constants.RESULT_OK)
   {
         if(in.remaining()<RESULT_CODE_LEN)
         {
              return null;
         }
         ResultMessage m=new ResultMessage();
         m.setOk(true);
         m.setValue(in.getInt());
         readCode=false;
         return m;
   }else{
       ResultMessage m=new ResultMessage();
         m.setOk(false);
         readCode=false;
         return m;
   }
     }
    @Override
    public void finishDecode(IoSession arg0, ProtocolDecoderOutput arg1)
     throws Exception {
    }
}

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import cn.com.unutrip.java.opensource.mina.sumup.message.ResultMessage;
/**
 * 加密消息头和消息的体的信息
 * @author longgangbai
 *
 * @param <T>
 */
public  class ResultMessageEncoder<T extends ResultMessage> extends  AbstractMessageEncoder<T> {
      public ResultMessageEncoder(){
   super(Constants.RESULT);
      }
     
      /**
       * 解析消息的体的方法的
       * @param session
       * @param message
       * @param out
       */
      protected  void encodeBody(IoSession session ,T message ,IoBuffer out)
      {
    if(message.isOk())
    {
        out.putShort((short)Constants.RESULT_OK);
        out.putInt(message.getValue());
    }else{
        out.putShort((short)Constants.RESULT_ERROR);
    }
      }
      /**
       * 
       * @throws Exception
       */
      public void dispose()throws Exception{}
}

package cn.com.unutrip.java.opensource.mina.sumup.codec;
/**
 * 定义解析的常量接口
 * @author longgangbai
 *
 */
public interface Constants {
         public static final int TYPE_LEN = 2;
         public static final int SEQUENCE_LEN = 4;
         public static final int HEADER_LEN = TYPE_LEN + SEQUENCE_LEN;
         public static final int BODY_LEN = 12;
         public static final int RESULT = 0;
         public static final int ADD = 1;
         public static final int RESULT_CODE_LEN = 2;
         public static final int RESULT_VALUE_LEN = 4;
         public static final int ADD_BODY_LEN = 4;
         public static final int RESULT_OK = 0;
         public static final int RESULT_ERROR = 1;
}

package cn.com.unutrip.java.opensource.mina.sumup.codec;
import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
import cn.com.unutrip.java.opensource.mina.sumup.message.AddMessage;
import cn.com.unutrip.java.opensource.mina.sumup.message.ResultMessage;
/**
 * 加密解密的解析工厂类
 * @author longgangbai
 *
 */
public class SumUpProtocolCodecFactory extends DemuxingProtocolCodecFactory {
   public SumUpProtocolCodecFactory(boolean server)
   {
       //注册服务端的操作
// 备注客户端和服务端的解析和加密的相反的消息体
       if(server)
       {
     super.addMessageDecoder(AddMessageDecoder.class);
     super.addMessageEncoder(ResultMessage.class, ResultMessageEncoder.class);
       //注册客户端的操作
       }else{
    super.addMessageEncoder(AddMessage.class,AddMessageEncoder.class);
    super.addMessageDecoder(ResultMessageDecoder.class);
       }
   }
}
消息实体类:
package cn.com.unutrip.java.opensource.mina.sumup.message;
import java.io.Serializable;
/**
 * 各种信息的基类
 * @author longgangbai
 *
 */
public abstract class AbstractMessage implements Serializable {
    private int sequence;
    public int getSequence() {
        return sequence;
    }
    
    public void setSequence(int sequence) {
        this.sequence = sequence;
    }
}
package cn.com.unutrip.java.opensource.mina.sumup.message;
/**
 * 发送信息的模型
 * @author longgangbai
 *
 */
public class AddMessage  extends AbstractMessage {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int value;
    public int getValue() {
        return value;
    }
    
    public void setValue(int value) {
        this.value = value;
    }
    @Override
    public String toString(){
   return getSequence()+"ADD ( "+value+")";
    }
  
}
package cn.com.unutrip.java.opensource.mina.sumup.message;
/**
 * 存储结构的模型的信息
 * @author longgangbai
 *
 */
public class ResultMessage extends AbstractMessage {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private boolean ok;
    private int value;
    public boolean isOk() {
        return ok;
    }
    public void setOk(boolean ok) {
        this.ok = ok;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    
    @Override
    public String toString(){
 if(ok){
     return getSequence()+" :RESULT ( " +value+")";
 }else{
     return  getSequence()+" :RESULT ( ERROR)";
 }
    }
  
}

在客户端和服务端的中定义相关的业务逻辑类的实现:通过实现IoHandler 中实现方法,操作各种业务。

一般的开发中采用IoHandlerAdapter,通过重写部分的方法实现的相关的业务逻辑;

IoHandler

IoHandler具有以下功能

  • sessionCreated sessionCreated
  • sessionOpened sessionOpened
  • sessionClosed sessionClosed
  • sessionIdle sessionIdle
  • exceptionCaught exceptionCaught
  • messageReceived messageReceived
  • messageSent messageSent

sessionCreated事件

Session Created event is fired when a new connection is created.

会话创建事件被激发时,一个新的连接被创建。

 For TCP its the result of connection accept, and for UDP this is generated when a UDP packet is received.

对于TCP的连接其结果接受,这是为UDP时生成一个UDP数据包接收。

 This function can be used to initialize session attributes, and perform one time activities for a particular connection.

该功能可用于初始化会话属性,并执行一次活动的特定连接。

This function is invoked from the I/O processor thread context, hence should be implemented in a way that it consumes minimal amount of time, as the same thread handles multiple sessions.

调用此函数从I / O处理器线程上下文,因此应该采取一种方式,它消耗最少量的时间,相同的线程处理多个会话执行。

sessionOpened Event sessionOpened事件

Session opened event is invoked when a connection is opened.

调用的事件是打开一个连接。

Its is always called after sessionCreated event.它总是sessionCreated事件后调用。 If a thread model is configured, this function is called in a thread other than the I/O processor thread.

如果一个线程模型配置,该函数被调用的线程比I / O处理器线程等。

sessionClosed Event sessionClosed事件

Session Closed event is closed, when a session is closed.

会话关闭时,当一个会话结束。

Session cleaning activities like cash cleanup can be performed here.

sessionIdle Event sessionIdle事件

Session Idle event is fired when a session becomes idle.

会议空闲事件被激发时,会变为空闲。

 This function is not invoked for UDP transport.

此功能没有援引UDP传输。

exceptionCaught Event exceptionCaught事件

This functions is called, when an Exception is thrown by user code or by MINA.

这个函数被调用,当异常是由用户代码或MINA的异常。

The connection is closed, if its an IOException.连接关闭,如果它的一个IOException。

messageReceived Event messageReceived事件

Message Received event is fired whenever a message is received.

消息收稿事件被激发时,收到一条消息。

This is where the most of the processing of an application happens.

这就是对一个应用程序处理大部分发生。

You need to take care of all the message type you expect here.

您需要考虑所有类型的信息在这里照顾你期望。

messageSent Event messageSent事件

Message Sent event is fired, whenever a message aka response has been sent(calling IoSession.write()).消息发送的事件被激发,每当有消息又名反应已发送(呼叫IoSession.write())。

 

 

客户端的业务逻辑处理器:

源代码如下:

package cn.com.unutrip.java.opensource.mina.sumup;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.com.unutrip.java.opensource.mina.sumup.message.AddMessage;
import cn.com.unutrip.java.opensource.mina.sumup.message.ResultMessage;
/**
 * 
 * 处理所有I / O活动的MINA的激發。
 *  The interface is hub of all activities done at the end of the Filter Chain.
 *  该接口是在过滤器链的末端进行的所有活动的中心。 
* IoHandler has following functions IoHandler具有以下功能 
* sessionCreated  :
*  会话创建事件被激发时,一个新的连接被创建。 For TCP its the result of connection accept, and for UDP this is generated when a UDP packet is received.对于TCP的连接其结果接受,这是为UDP时生成一个UDP数据包接收。 This function can be used to initialize session attributes, and perform one time activities for a particular connection.该功能可用于初始化会话属性,并执行一次活动的特定连接。 
*This function is invoked from the I/O processor thread context, hence should be implemented in a way that it consumes minimal amount of time, as the same thread handles multiple sessions.调用此函数从I / O处理器线程上下文,因此应该采取一种方式,它消耗最少量的时间,相同的线程处理多个会话执行。 
* 
* sessionOpened  :会话开始一个连接时调用此事件,它总在sessionCreated事件后调用,如果一个线程模型配置
* 该函数被调用的的线程IoHandler。
*  
* sessionClosed  : 当一个会话结束,session清理活动的活动的连接。
*  
* sessionIdle  : 此方法被激发时,会变成空闲,此功能没有援引UDP传输。
*  
* exceptionCaught   : 当用户代码或者mina异常是,连接关闭,如果它的一个连接IOException
* 
* messageReceived :  当接受到一个消息时被激发,对应一个应用程序的处理的大部分业务逻辑,
*  
* messageSent  : 消息发送的时间被激发,
* 
*  调用的事件是打开一个连接。 Its is always called after sessionCreated event.它总是sessionCreated事件后调用。
*   If a thread model is configured, this function is called in a thread other than the I/O processor thread.
*   如果一个线程模型配置,该函数被调用的线程比I / O处理器线程等。
 * 
 * 客户端业务处理器的应用
 * 
 * @author longgangbai
 *
 */
public class ClientSessionHandler extends IoHandlerAdapter {
    private final static Logger logger = LoggerFactory.getLogger(ClientSessionHandler.class);
          
          private final int[] values;
      
          private boolean finished;
      
          public ClientSessionHandler(int[] values) {
              this.values = values;
          }
      
          public boolean isFinished() {
              return finished;
          }
          /**
           *  
           *  调用的事件是打开一个连接。 Its is always called after sessionCreated event.
           *  它总是sessionCreated事件后调用。 
           *  If a thread model is configured, this function is called in a thread other than the I/O processor thread.
           *  如果一个线程模型配置,该函数被调用的线程比I / O处理器线程等。 
           */
          @Override
          public void sessionOpened(IoSession session) {
              logger.error("ClientSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionOpened ");
              // send summation requests
              for (int i = 0; i < values.length; i++) {
                  AddMessage m = new AddMessage();
                  m.setSequence(i);
                  m.setValue(values[i]);
                  session.write(m);
              }
          }
          /**
           * 接受来自服务端的数据信息
           * 接受到消息事件被激发时,收到一条消息。
           *  This is where the most of the processing of an application happens.
           * 这就是对一个应用程序处理大部分发生。
           *  You need to take care of all the message type you expect here.
           *  您需要考虑所有类型的信息在这里照顾你期望。(重要的业务逻辑的写这里)
           */
          @Override
          public void messageReceived(IoSession session, Object message) {
              logger.error("ClientSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%messageReceived ");
              // server only sends ResultMessage. otherwise, we will have to identify
              // its type using instanceof operator.
              ResultMessage rm = (ResultMessage) message;
              if (rm.isOk()) {
                  // server returned OK code.
                  // if received the result message which has the last sequence
                  // number,
                  // it is time to disconnect.
                  if (rm.getSequence() == values.length - 1) {
                      // print the sum and disconnect.
                      logger.error("The sum: " + rm.getValue());
                      session.close(true);
                      finished = true;
                  }
              } else {
                  // seever returned error code because of overflow, etc.
                  logger.error("Server error, disconnecting...");
                  session.close(true);
                  finished = true;
              }
          }
      
         /**
          * 发生异常时的操作
          * 当异常是由用户代码或MINA的异常。 The connection is closed, if its an IOException.连接关闭,如果它的一个IOException
          */ 
         @Override
         public void exceptionCaught(IoSession session, Throwable cause) {
            logger.error("ClientSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%exceptionCaught ");
            session.close(true);
         }
}
服务端的业务逻辑处理器:
package cn.com.unutrip.java.opensource.mina.sumup;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.com.unutrip.java.opensource.mina.sumup.message.AddMessage;
import cn.com.unutrip.java.opensource.mina.sumup.message.ResultMessage;
/**
 *  创建服务端的业务处理器
 * @author longgangbai
 *
 */
public class ServerSessionHandler extends IoHandlerAdapter{
    private static final String SUM_KEY="sum";
    private final static Logger logger=LoggerFactory.getLogger(ServerSessionHandler.class); 
    
    @Override
    public void sessionOpened(IoSession session){
 logger.error("ServerSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionOpened ");
 //设置Idle的时间为60秒
 session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
 //初始化总的和为0 
 session.setAttribute(SUM_KEY,new Integer(0));
    }
    @Override
    public void sessionIdle(IoSession session,IdleStatus statis)
    {
 logger.error("ServerSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%sessionIdle ");
 logger.info("Disconnecting the idle.");
 // disconnect an idle client
 session.close(true);
    }
    
     @Override
     public void exceptionCaught(IoSession session, Throwable cause) {
  logger.error("ServerSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%exceptionCaught ");
         // close the connection on exceptional situation
          session.close(true);
      }
     @Override
    public void messageReceived(IoSession session ,Object message){
  logger.error("ServerSessionHandler =%%%%%%%%%%%%%%%%%%%%%%%%%%%messageReceived ");
  //客户端发送的对象必须住注册的对象一致
 AddMessage am=(AddMessage)message;
 //将客户端的发送的数据添加到当前总的金额中
 int sum=(Integer)session.getAttribute(SUM_KEY);
 int value=am.getValue();
 long expectedsum=(long)sum+value;
 
 if(expectedsum>Integer.MAX_VALUE||expectedsum<Integer.MIN_VALUE)
 {
     //
     ResultMessage rm=new ResultMessage();
     rm.setSequence(am.getSequence());
     rm.setOk(false);
     session.write(rm);
 }else{
      sum=(int)expectedsum;
      session.setAttribute(SUM_KEY,new Integer(sum));
      ResultMessage rm=new ResultMessage();
      rm.setSequence(am.getSequence());
      rm.setOk(true);
      rm.setValue(sum);
      session.write(rm);
 }
    }
}

在客户端和服务端的调用如下:

 

客户端;

package cn.com.unutrip.java.opensource.mina.sumup;
import java.net.InetSocketAddress;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import cn.com.unutrip.java.opensource.mina.sumup.codec.SumUpProtocolCodecFactory;
/**
 * TCP/ID 客户端的应用
 * @author longgangbai
 *
 */
public class Client {
          private static final String HOSTNAME = "localhost";
          private static final int PORT = 8123;
      
          private static final long CONNECT_TIMEOUT = 30*1000L; // 30 seconds
      
          // Set this to false to use object serialization instead of custom codec.
          private static final boolean USE_CUSTOM_CODEC = true;
      
          public static void main(String[] args) throws Throwable {
              // prepare values to sum up
              int[] values = new int[10];
              for (int i = 0; i < args.length; i++) {
                  values[i] = Integer.parseInt(args[i]);
              }
              //创建一个客户端对象
              NioSocketConnector connector = new NioSocketConnector();
      
              // Configure the service.
              //设置连接超时时间
              connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);
              //获取过滤器链工厂
              DefaultIoFilterChainBuilder filterchain=connector.getFilterChain();
              //添加相应的过滤链
              if (USE_CUSTOM_CODEC) {
           //采用自定义的协议编码工厂类过滤器连
           filterchain.addLast("codec",new ProtocolCodecFilter(new SumUpProtocolCodecFactory(false)));
              } else {
           //采用对象序列化编码工厂类过滤器连
           filterchain.addLast("codec",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
              }
              //添加日志过滤器连
              filterchain.addLast("logger", new LoggingFilter());
              //进行业务处理逻辑
              connector.setHandler(new ClientSessionHandler(values));
      
              IoSession session=null;
              for (;;) {
                  try {
                     ConnectFuture future = connector.connect(new InetSocketAddress(
                              HOSTNAME, PORT));
                      future.awaitUninterruptibly();
                      session = future.getSession();
                      break;
                  } catch (RuntimeIoException e) {
                      System.err.println("Failed to connect.");
                      e.printStackTrace();
                      Thread.sleep(5000);
                  }
              }
              // wait until the summation is done
              session.getCloseFuture().awaitUninterruptibly();
              connector.dispose();
          }
      }

服务端使用如下:

package cn.com.unutrip.java.opensource.mina.sumup;
import java.net.InetSocketAddress;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import cn.com.unutrip.java.opensource.mina.sumup.codec.SumUpProtocolCodecFactory;
/**
 *TCP /IP 服务端的代码的应用
 * @author longgangbai
 *
 */
public class Server {
    private static final int SERVER_PORT = 8123;
          // Set this to false to use object serialization instead of custom codec.
          private static final boolean USE_CUSTOM_CODEC = true;
      
          public static void main(String[] args) throws Throwable {
              //创建服务端
              NioSocketAcceptor acceptor = new NioSocketAcceptor();
              //获取过滤链的信息
              DefaultIoFilterChainBuilder filterchain=acceptor.getFilterChain();
              // Prepare the service configuration.
              if (USE_CUSTOM_CODEC) {
           filterchain.addLast("codec",new ProtocolCodecFilter(new SumUpProtocolCodecFactory(true)));
              } else {
           filterchain.addLast("codec",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
              }
              filterchain.addLast("logger", new LoggingFilter());
              //业务处理
              acceptor.setHandler(new ServerSessionHandler());
              //绑定服务端口
              acceptor.bind(new InetSocketAddress(SERVER_PORT));
              System.out.println("Listening on port " + SERVER_PORT);
          }
}
 






转载地址:http://www.iteye.com/topic/585834

Apache Mina是一个用于开发高性能、高可扩展性网络应用程序的Java框架。它提供了一种简单和灵活的方式来构建基于TCP/IP和UDP/IP协议的客户端和服务器端应用。 在学习Apache Mina时,首先需要了解它的基本概念和架构。Mina采用了NIO(非阻塞IO)的方式来实现网络通信。它的核心组件是IoService,它负责接收客户端的连接请求,并将请求分发给对应的I/O处理器进行处理。而I/O处理器则负责实际的数据读写和业务逻辑的处理。 在使用Mina进行开发时,我们首先需要创建一个IoAcceptor对象来监听指定的端口,并设置相应的处理器。当有客户端发起连接请求时,IoAcceptor会接收并处理这些请求。同时,我们还需要编写相应的I/O处理器来对接收到的数据进行处理和响应。 Mina还提供了一些便捷的工具类和接口,以简化开发过程。例如,可以使用IoBuffer来处理数据的读写,它类似于Java NIO中的ByteBuffer。同时,Mina还提供了一些过滤器,可以在数据传输的过程中进行一些常用的操作,比如加密、压缩、编解码等。 值得一提的是,Mina支持多种编解码协议,包括自定义的协议。它可以根据指定的编解码规则将数据进行解析和组装。这在实际应用中非常实用,因为经常会遇到需要对传输的数据进行编码和解码的情况。 总的来说,学习Apache Mina需要了解其基本概念、架构和核心组件,并掌握基本的开发流程和常用的工具类和接口。通过学习Mina,我们可以更加方便地开发出高性能、高可扩展性的网络应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值