dong5300 发表于 2018-11-23 06:15:03

apache mina自定义消息传输

对于Apache Mina不太熟悉的童鞋,请移步到如下百度百科连接进行学习了解:
http://baike.baidu.com/view/2668084.htm
首先建立一个new project(Server端),这里使用IDE是 eclipse;
OK,首先我们这里先配置下环境:对于Mina的日志输出使用的是slf4j,对于slf4j在开发Hibernate的时候已经很熟悉了,不需要再介绍了。另外一方面就是加入mina的core核心jar包;
1. mina-core.jar         2. slf4j-api.jar         3.slf4j-simple.jar
下面我们来书写server端的main函数类:

public class gamemain {
    private static final int PORT = 8888;
    public static void main(String[] args) throws IOException {
      IoAcceptor acceptor = new NioSocketAcceptor();
      acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
      DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
      // code will go here next
      ProtocolCodecFilter filter= new ProtocolCodecFilter(new ProtobufCodecFactory());
      //ProtobufCodecFactory 是自定义的编码工厂 需要自己实现   这个才可以实现自定义消息传输
      chain.addLast("objectFilter",filter);
      acceptor.setHandler(new ServerHandler() );
      acceptor.getSessionConfig().setReadBufferSize( 2048 );
      acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
      acceptor.bind( new InetSocketAddress(PORT) );
                                                                                                                                                
      System.out.print("game server is start!\n");
      Netmessage mess=new Netmessage();
      mess.setCode((short)1);
      EventManager.getInstance().addNetListener(mess, new LoginListener());
    }
}设置一个过滤器作用是将来自客户端输入的信息转换成自定义消息object后传递给 IoHandler,因此我们可以在 messageReceived 中直接将 msg 对象强制转换成 String 对象。

ProtocolCodecFilter filter= new ProtocolCodecFilter(new ProtobufCodecFactory());
       //ProtobufCodecFactory 是自定义的编码工厂 需要自己实现   这个才可以实现自定义消息传输
       chain.addLast("objectFilter",filter);设置好过滤器后,接下就必须重写编码工厂。
ProtobufCodecFactory继承自ProtocolCodecFactory类
实现大致是这样的:
public class ProtobufCodecFactory implements ProtocolCodecFactory{
    private static final ProtobufEncoder ENCODER_INSTANCE = new ProtobufEncoder();
    private static final ProtobufDecoder DECODER_INSTANCE = new ProtobufDecoder();
    public ProtobufCodecFactory() {
    }
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
      return DECODER_INSTANCE;
    }
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
      return ENCODER_INSTANCE;
    }
}然后实现自己的ProtobufEncoder和ProtobufDecoder
要正常实现与c++通信,必须根据自定义数据来实现
写一个简单的实现方案:
public class ProtobufDecoder extends CumulativeProtocolDecoder {
    private static final Logger log = Logger.getLogger(ProtobufDecoder.class);
    protected ProtobufDecoder() {
    }
    /**
   * 把二进制流解码为服务器使用的数据包格式
   */
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
//      private short size;//包大小
//      private short type;//版本号
//      private short code;//包类型
//      private int roleid; // 玩家ID
      IoBuffer newBuf = in.slice();
      //size
      int size = newBuf.getShort();
      System.out.printf("c size = %d\n",size);
      if (size = Short.MAX_VALUE) {
            // 非法的数据长度
            log.debug("Message Length Invalid size = " + size + ", throw this Message.");
            return true;
      }
      System.out.print(newBuf.getHexDump());
      //000A 0001 0001 0000 0001
      System.out.printf("buffer size = %d",in.remaining());
      if (size > in.remaining()) {
            // 数据还不够读取,等待下一次读取
            System.out.printf("Data not integrity. there is a lack of " + (size - newBuf.remaining()) + " bytes.");
            return true;
      }
      Netmessage res=new Netmessage();
      short type=newBuf.getShort();
      short code=newBuf.getShort();
      int roleid=newBuf.getInt();
      //int roleid=newBuf.getInt();
      System.out.printf("type =%d code = %d roleid = %d\n",(int)type,(int)code,roleid);
      res.writeDataPack((short)size, type, code, roleid);
      // BODY
      int bodyLen = size-10;
      if (bodyLen > 0) {
            byte[] bytes = new byte;
            in.get(bytes, 0, bodyLen);
            res.writeData(bytes,size);
      }
      out.write(res);
      return false;
    }
}大致是这样,余下的读者可以自己去实现,ps:apache mina 开发 群http://url.cn/Pc252w
本文long原创



页: [1]
查看完整版本: apache mina自定义消息传输