首先本身定義一個消息格式:java
package fhq; option java_package = "com.wesker.protocol"; option java_outer_classname = "ProtocolTypeMessage"; enum ProtocolType{ EXCEPTION = 1; INFO = 2; SHUTDOWN = 3; EVALUATE_TO_TYPESET = 4; EVALUATE_TO_MATHML = 5; }
package fhq; option java_package = "com.wesker.protocol"; option java_outer_classname = "ProtocolMessage"; import "ProtocolTypeMessage"; message Protocol { required ProtocolType type = 1; required bytes data = 2; }
這裏的Protocol就是咱們要處理的消息了。type是消息類型,data是數據。接下來生成java代碼:shell
protoc --java_out=/home/michael/protocol/ ProtocolTypeMessage protoc --java_out=/home/michael/protocol/ ProtocolMessage
接下來就是定義基於netty的消息轉換器了,一個編碼:將自定義的消息轉換成byte[]。 這裏用範型指定咱們剛纔定義好的消息類型。bootstrap
public class MessageEncoder extends MessageToByteEncoder<Protocol>{ @Override protected void encode(ChannelHandlerContext context, Protocol protocol, ByteBuf out) throws Exception { byte[] data = protocol.toByteArray(); out.writeInt(data.length); out.writeBytes(data); } }
一個解碼:將byte[]轉換成自定義的消息ide
public class MessageDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() < 4) { return; } in.markReaderIndex(); int dataLength = in.readInt(); if (in.readableBytes() < dataLength) { in.resetReaderIndex(); return; } byte[] decoded = new byte[dataLength]; in.readBytes(decoded); out.add(Protocol.parseFrom(decoded)); } }
在初始化server的時候將這2個東西放進去,和一個server處理自定義消息的handlerui
public class MyServerHandler extends SimpleChannelInboundHandler<Protocol>{ @Override protected void messageReceived(ChannelHandlerContext arg0, Protocol arg1) throws Exception { //do something..... } }
ServerBootstrap boot = new ServerBootstrap(); boot.group(core.getBoss(), core.getWorker()).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>(){ @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); SSLEngine engine = core.getSslContext().createSSLEngine(); engine.setUseClientMode(false); p.addLast("ssl", new SslHandler(engine)); p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast("encoder", new MessageEncoder());//在這裏 p.addLast("decoder", new MessageDecoder());//在這裏 p.addLast("MyServerHandler", new MyServerHandler());//server端處理消息 }});
一樣客戶端也要作一樣的事情:google
public class MyClientHandler extends SimpleChannelInboundHandler<Protocol>{ @Override protected void messageReceived(ChannelHandlerContext arg0, Protocol arg1) throws Exception { //do something..... } }
Bootstrap bootstrap = new Bootstrap(); bootstrap.group(core.getGroup()).channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>(){ @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); SSLEngine engine = core.getSslContext().createSSLEngine(); engine.setUseClientMode(true); p.addLast("ssl", new SslHandler(engine)); p.addLast("encoder", new MessageEncoder());//這裏 p.addLast("decoder", new MessageDecoder());//這裏 p.addLast("MyClientHandler", new MyClientHandler());//client端處理消息 }});
到這裏你就能夠使用本身的消息格式了。編碼
Netty 4之後都自帶了對google-protocol-buffer的解析器 : spa
ProtobufDecoder ProtobufEncoder
懶得本身定義就用這個。須要注意的是,ProtobufDecoder須要一個protocol-buffer的實例來才能初始化。(調用getDefaultInstance())netty
寫的很是倉促。。。。。。可能好多地方沒有寫明白。。有什麼問題你們能夠圈我。code