Mina自定义协议-实现数据交互

本文主要现实mina的自定义协议,并且实现服务器和客户端的简单数据交互。

 

"mina协议的自定义"可参考本博Mina相关文章。

 

正题,所需要的基础类:

抽象协议类

请求协议

响应协议

(需要定制自己的协议格式)

 

协议编码解码工厂

协议编码

协议解码

 

客户端

客户端Handler

 

服务器

服务器Handler

 

 

Java代码   收藏代码
  1. /** 
  2.  * 消息协议 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public abstract class JAbsMessageProtocal {  
  8.   
  9.   public abstract byte getTag();// 消息协议类型  请求/响应  
  10.   
  11.   public abstract int getLength();// 消息协议数据长度  
  12. }  
  13.   
  14. /** 
  15.  * 报头: 
  16.  *    short tag:请求/响应 
  17.  *    int   length:数据长度 
  18.  * 报体: 
  19.  *    short   methodCode:功能函数 
  20.  *    byte    resultCode:结果码 
  21.  *    String  content:数据内容 
  22.  */  
 

 

 

Java代码   收藏代码
  1. /** 
  2.  * 消息协议-请求 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class JMessageProtocalReq extends JAbsMessageProtocal {  
  8.   
  9.   private short functionCode;// 功能代码  
  10.   
  11.   private String content;// 请求内容  
  12.   
  13.   @Override  
  14.   public int getLength() {  
  15.     return 2 + (content == null ? 0 : content.getBytes().length);  
  16.   }  
  17.   
  18.   @Override  
  19.   public byte getTag() {  
  20.     return JConstant.REQ;  
  21.   }  
  22.   
  23.   public void setFunctionCode(short functionCode) {  
  24.     this.functionCode=functionCode;  
  25.   }  
  26.   
  27.   public short getFunctionCode() {  
  28.     return functionCode;  
  29.   }  
  30.   
  31.   public void setContent(String content) {  
  32.     this.content=content;  
  33.   }  
  34.   
  35.   public String getContent() {  
  36.     return content;  
  37.   }  
  38.   
  39.   @Override  
  40.   public String toString() {  
  41.     return "JMessageProtocalReq [content=" + content + ", functionCode=" + functionCode + ", getLength()=" + getLength()  
  42.       + ", getTag()=" + getTag() + "]";  
  43.   }  
  44. }  
 

 

 

Java代码   收藏代码
  1. /** 
  2.  * 消息协议-响应 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class JMessageProtocalRes extends JAbsMessageProtocal {  
  8.   
  9.   private byte resultCode;// 结果码  
  10.   
  11.   private String content;// 响应内容  
  12.   
  13.   @Override  
  14.   public int getLength() {  
  15.     return 1 + (getContent() == null ? 0 : getContent().getBytes().length);  
  16.   }  
  17.   
  18.   @Override  
  19.   public byte getTag() {  
  20.     return JConstant.RES;  
  21.   }  
  22.   
  23.   public void setResultCode(byte resultCode) {  
  24.     this.resultCode=resultCode;  
  25.   }  
  26.   
  27.   public byte getResultCode() {  
  28.     return resultCode;  
  29.   }  
  30.   
  31.   public void setContent(String content) {  
  32.     this.content=content;  
  33.   }  
  34.   
  35.   public String getContent() {  
  36.     return content;  
  37.   }  
  38.   
  39.   @Override  
  40.   public String toString() {  
  41.     return "JMessageProtocalRes [content=" + content + ", resultCode=" + resultCode + ", getLength()=" + getLength()  
  42.       + ", getTag()=" + getTag() + "]";  
  43.   }  
  44. }  

 

Java代码   收藏代码
  1. /** 
  2.  * JMessageProtocal解码编码工厂 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class JMessageProtocalCodecFactory implements ProtocolCodecFactory {  
  8.   
  9.   private final JMessageProtocalDecoder decoder;  
  10.   
  11.   private final JMessageProtocalEncoder encoder;  
  12.   
  13.   public JMessageProtocalCodecFactory(Charset charset) {  
  14.     this.decoder=new JMessageProtocalDecoder(charset);  
  15.     this.encoder=new JMessageProtocalEncoder(charset);  
  16.   }  
  17.   
  18.   public ProtocolDecoder getDecoder(IoSession paramIoSession) throws Exception {  
  19.     return decoder;  
  20.   }  
  21.   
  22.   public ProtocolEncoder getEncoder(IoSession paramIoSession) throws Exception {  
  23.     return encoder;  
  24.   }  
  25. }  

 

Java代码   收藏代码
  1. /** 
  2.  * JMessageProtocal解码 
  3.  * @author Simple 
  4.  * 
  5.  */  
  6. public class JMessageProtocalDecoder extends ProtocolDecoderAdapter {  
  7.   
  8.   private Logger log=Logger.getLogger(JMessageProtocalDecoder.class);  
  9.   
  10.   private Charset charset;  
  11.   
  12.   public JMessageProtocalDecoder(Charset charset) {  
  13.     this.charset=charset;  
  14.   }  
  15.   
  16.   /** 
  17.    * 解码 
  18.    */  
  19.   public void decode(IoSession session, IoBuffer buf, ProtocolDecoderOutput out) throws Exception {  
  20.     JAbsMessageProtocal absMP=null;  
  21.     // 获取协议tag  
  22.     byte tag=buf.get();  
  23.     // 获取协议体长度  
  24.     int length=buf.getInt();  
  25.     // 取出协议体  
  26.     byte[] bodyData=new byte[length];  
  27.     buf.get(bodyData);  
  28.     // 为解析数据做准备  
  29.     // 检测协议  
  30.     IoBuffer tempBuf=IoBuffer.allocate(100).setAutoExpand(true);  
  31.     tempBuf.put(tag);  
  32.     tempBuf.putInt(length);  
  33.     tempBuf.put(bodyData);  
  34.     tempBuf.flip();  
  35.     if(!canDecode(tempBuf)) {  
  36.       return;  
  37.     }  
  38.     // 协议体buf  
  39.     IoBuffer bodyBuf=IoBuffer.allocate(100).setAutoExpand(true);  
  40.     bodyBuf.put(bodyData);  
  41.     bodyBuf.flip();  
  42.     // 整个协议buf  
  43.     IoBuffer allBuf=IoBuffer.allocate(100).setAutoExpand(true);  
  44.     allBuf.put(tag);  
  45.     allBuf.putInt(length);  
  46.     allBuf.put(bodyData);  
  47.     allBuf.flip();  
  48.     //  
  49.     if(tag == JConstant.REQ) {  
  50.       JMessageProtocalReq req=new JMessageProtocalReq();  
  51.       short functionCode=bodyBuf.getShort();  
  52.       String content=bodyBuf.getString(charset.newDecoder());  
  53.       req.setFunctionCode(functionCode);  
  54.       req.setContent(content);  
  55.       absMP=req;  
  56.     } else if(tag == JConstant.RES) {  
  57.       JMessageProtocalRes res=new JMessageProtocalRes();  
  58.       byte resultCode=bodyBuf.get();  
  59.       String content=bodyBuf.getString(charset.newDecoder());  
  60.       res.setResultCode(resultCode);  
  61.       res.setContent(content);  
  62.       absMP=res;  
  63.     } else {  
  64.       log.error("未定义的Tag");  
  65.     }  
  66.     out.write(absMP);  
  67.   }  
  68.   
  69.   // 是否可以解码  
  70.   private boolean canDecode(IoBuffer buf) {  
  71.     int protocalHeadLength=5;// 协议头长度  
  72.     int remaining=buf.remaining();  
  73.     if(remaining < protocalHeadLength) {  
  74.       log.error("错误,协议不完整,协议头长度小于" + protocalHeadLength);  
  75.       return false;  
  76.     } else {  
  77.       log.debug("协议完整");  
  78.       // 获取协议tag  
  79.       byte tag=buf.get();  
  80.       if(tag == JConstant.REQ || tag == JConstant.RES) {  
  81.         log.debug("Tag=" + tag);  
  82.       } else {  
  83.         log.error("错误,未定义的Tag类型");  
  84.         return false;  
  85.       }  
  86.       // 获取协议体长度  
  87.       int length=buf.getInt();  
  88.       if(buf.remaining() < length) {  
  89.         log.error("错误,真实协议体长度小于消息头中取得的值");  
  90.         return false;  
  91.       } else {  
  92.         log.debug("真实协议体长度:" + buf.remaining() + " = 消息头中取得的值:" + length);  
  93.       }  
  94.     }  
  95.     return true;  
  96.   }  
  97. }  

 

Java代码   收藏代码
  1. /** 
  2.  * JMessageProtocal编码 
  3.  * @author Simple 
  4.  * 
  5.  */  
  6. public class JMessageProtocalEncoder extends ProtocolEncoderAdapter {  
  7.   
  8.   private Charset charset;  
  9.   
  10.   public JMessageProtocalEncoder(Charset charset) {  
  11.     this.charset=charset;  
  12.   }  
  13.   
  14.   /** 
  15.    * 编码 
  16.    */  
  17.   public void encode(IoSession session, Object object, ProtocolEncoderOutput out) throws Exception {  
  18.     // new buf  
  19.     IoBuffer buf=IoBuffer.allocate(2048).setAutoExpand(true);  
  20.     // object --> AbsMP  
  21.     JAbsMessageProtocal absMp=(JAbsMessageProtocal)object;  
  22.     buf.put(absMp.getTag());  
  23.     buf.putInt(absMp.getLength());  
  24.     if(object instanceof JMessageProtocalReq) {// 请求协议  
  25.       JMessageProtocalReq mpReq=(JMessageProtocalReq)object;  
  26.       buf.putShort(mpReq.getFunctionCode());  
  27.       buf.putString(mpReq.getContent(), charset.newEncoder());  
  28.     } else if(object instanceof JMessageProtocalRes) {// 响应协议  
  29.       JMessageProtocalRes mpRes=(JMessageProtocalRes)object;  
  30.       buf.put(mpRes.getResultCode());  
  31.       buf.putString(mpRes.getContent(), charset.newEncoder());  
  32.     }  
  33.     buf.flip();  
  34.     out.write(buf);  
  35.   }  
  36. }  

 

Java代码   收藏代码
  1. /** 
  2.  * MINA 客户端 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class MainClient {  
  8.   
  9.   @SuppressWarnings("unused")  
  10.   private static Logger log=Logger.getLogger(MainClient.class);  
  11.   
  12.   private static final int PORT=9999;  
  13.   
  14.   public static void main(String[] args) {  
  15.     NioSocketConnector connector=new NioSocketConnector();  
  16.     DefaultIoFilterChainBuilder chain=connector.getFilterChain();  
  17.     chain.addLast("ProtocolCodecFilter"new ProtocolCodecFilter(new JMessageProtocalCodecFactory(Charset.forName("UTF-8"))));  
  18.     connector.setHandler(new MinaClientHandler());  
  19.     connector.setConnectTimeoutMillis(3000);  
  20.     ConnectFuture cf=connector.connect(new InetSocketAddress("localhost", PORT));  
  21.     cf.awaitUninterruptibly();// 等待连接创建完成  
  22.     JMessageProtocalReq req=new JMessageProtocalReq();  
  23.     req.setFunctionCode((short)1);  
  24.     req.setContent("hello world!!!");  
  25.     cf.getSession().write(req);  
  26.     cf.getSession().getCloseFuture().awaitUninterruptibly();// 等待连接断开  
  27.     connector.dispose();  
  28.   }  
  29. }  

 

Java代码   收藏代码
  1. /** 
  2.  * MINA 客户端消息处理 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class MinaClientHandler extends IoHandlerAdapter {  
  8.   
  9.   private Logger log=Logger.getLogger(MinaClientHandler.class);  
  10.   
  11.   @Override  
  12.   public void exceptionCaught(IoSession session, Throwable cause) throws Exception {  
  13.     log.error(String.format("Client产生异常!"));  
  14.   }  
  15.   
  16.   @Override  
  17.   public void messageReceived(IoSession session, Object message) throws Exception {  
  18.     log.debug(String.format("来自Server[%s]的消息:%s", session.getRemoteAddress(), message.toString()));  
  19.   }  
  20.   
  21.   @Override  
  22.   public void messageSent(IoSession session, Object message) throws Exception {  
  23.     log.debug(String.format("向Server[%s]发送消息:%s", session.getRemoteAddress(), message.toString()));  
  24.   }  
  25.   
  26.   @Override  
  27.   public void sessionClosed(IoSession session) throws Exception {  
  28.     log.debug(String.format("与Server[%s]断开连接!", session.getRemoteAddress()));  
  29.   }  
  30.   
  31.   @Override  
  32.   public void sessionCreated(IoSession session) throws Exception {  
  33.     log.debug(String.format("与Server[%s]建立连接!", session.getRemoteAddress()));  
  34.   }  
  35.   
  36.   @Override  
  37.   public void sessionOpened(IoSession session) throws Exception {  
  38.     log.debug(String.format("与Server[%s]打开连接!", session.getRemoteAddress()));  
  39.   }  
  40.   
  41.   @Override  
  42.   public void sessionIdle(IoSession session, IdleStatus status) throws Exception {  
  43.     log.debug(String.format("Client进入空闲状态!"));  
  44.   }  
  45. }  

 

Java代码   收藏代码
  1. /** 
  2.  * MINA 服务器 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class MainServer {  
  8.   
  9.   private static Logger log=Logger.getLogger(MainServer.class);  
  10.   
  11.   private static final int PORT=9999;  
  12.   
  13.   public static void main(String[] args) throws Exception {  
  14.     SocketAcceptor acceptor=new NioSocketAcceptor();// tcp/ip 接收者  
  15.     DefaultIoFilterChainBuilder chain=acceptor.getFilterChain();// 过滤管道  
  16.     chain.addLast("ProtocolCodecFilter"new ProtocolCodecFilter(new JMessageProtocalCodecFactory(Charset.forName("UTF-8"))));  
  17.     acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);// 读写通道10s内无操作进入空闲状态  
  18.     acceptor.setHandler(new MinaServerHandler());// 设置handler  
  19.     acceptor.bind(new InetSocketAddress(PORT));// 设置端口  
  20.     log.debug(String.format("Server Listing on %s", PORT));  
  21.   }  
  22. }  

 

Java代码   收藏代码
  1. /** 
  2.  * MINA 服务器消息处理 
  3.  *  
  4.  * @author Simple 
  5.  *  
  6.  */  
  7. public class MinaServerHandler extends IoHandlerAdapter {  
  8.   
  9.   private Logger log=Logger.getLogger(MinaServerHandler.class);  
  10.   
  11.   @Override  
  12.   public void exceptionCaught(IoSession session, Throwable cause) throws Exception {  
  13.     log.error(String.format("Server产生异常!"));  
  14.   }  
  15.   
  16.   @Override  
  17.   public void messageReceived(IoSession session, Object message) throws Exception {  
  18.     log.debug(String.format("来自Client[%s]的消息:%s", session.getRemoteAddress(), message.toString()));  
  19.   }  
  20.   
  21.   @Override  
  22.   public void messageSent(IoSession session, Object message) throws Exception {  
  23.     log.debug(String.format("向Client[%s]发送消息:%s", session.getRemoteAddress(), message.toString()));  
  24.   }  
  25.   
  26.   @Override  
  27.   public void sessionClosed(IoSession session) throws Exception {  
  28.     log.debug(String.format("Client[%s]与Server断开连接!", session.getRemoteAddress()));  
  29.   }  
  30.   
  31.   @Override  
  32.   public void sessionCreated(IoSession session) throws Exception {  
  33.     log.debug(String.format("Client[%s]与Server建立连接!", session.getRemoteAddress()));  
  34.   }  
  35.   
  36.   @Override  
  37.   public void sessionIdle(IoSession session, IdleStatus status) throws Exception {  
  38.     log.debug(String.format("Server进入空闲状态!"));  
  39.   }  
  40.   
  41.   @Override  
  42.   public void sessionOpened(IoSession session) throws Exception {  
  43.     log.debug(String.format("Client[%s]与Server打开连接!", session.getRemoteAddress()));  
  44.   }  
  45. }  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值