對於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原創