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 <= 0 || 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[bodyLen];
            in.get(bytes, 0, bodyLen);
            res.writeData(bytes,size);
        }
        out.write(res);
        return false;
    }
}

大致是這樣,餘下的讀者可以自己去實現,ps:apache mina 開發 羣http://url.cn/Pc252w

本文long原創

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章