Netty 實現自定義消息格式

Netty 實現基於google-protocol-buffer自定義消息格式

首先本身定義一個消息格式: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

相關文章
相關標籤/搜索