Netty详解(七):Netty 编解码以及消息头编解码器
1. MessagePack 概述
MessagePack是一個高效的二進制序列化框架,像JSON一樣支持不同語言間的數據交換,速度更快,序列化之后的碼流更小。
MessagePacke優點
- 編解碼高效,性能高
- 序列化后的碼流小
- 支持跨語言
1.1 MessagePack Java API 介紹
<dependencies>...<dependency><groupId>org.msgpack</groupId><artifactId>msgpack</artifactId><version>${msgpack.version}</version></dependency>... </dependencies>1.2 API 官方示例:
import java.io.IOException; import java.util.ArrayList; import java.util.List;import org.msgpack.MessagePack; import org.msgpack.template.Templates;public class TestMessagePack {public static void main(String[] args) {// Create serialize objectsList<String> src=new ArrayList<String>();src.add("msgpack");src.add("kumofs");src.add("viver");MessagePack msgpack=new MessagePack();// Serializebyte[] raw;try {raw = msgpack.write(src);// Deserialize directly using a templateList<String> dst1 = msgpack.read(raw,Templates.tList(Templates.TString));System.out.println(dst1.get(0));System.out.println(dst1.get(1));System.out.println(dst1.get(2));} catch (IOException e) {e.printStackTrace();}}}2. Netty 編碼器和解碼器開發
2.1 Netty編碼器
import org.msgpack.MessagePack;import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder;public class MsgpackEncoder extends MessageToByteEncoder<Object> {@Overrideprotected void encode(ChannelHandlerContext arg0, Object arg1, ByteBuf arg2) throws Exception {MessagePack msgpack=new MessagePack();byte[] raw=msgpack.write(arg1);arg2.writeBytes(raw);} }Netty編碼繼承MessageToByteEncoder,它負責將Object類型的POJO對象編碼成byte數組,然后寫入到ByteBuffer中。
2.2 Netty解碼器
import java.util.List;import org.msgpack.MessagePack;import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder;public class MsgPackDecoder extends MessageToMessageDecoder<ByteBuf> {@Overrideprotected void decode(ChannelHandlerContext arg0, ByteBuf arg1, List<Object> arg2) throws Exception {final byte[] array;final int length=arg1.readableBytes();array=new byte[length];arg1.getBytes(arg1.readerIndex(), array,0,length);MessagePack msgpack=new MessagePack();arg2.add(msgpack.read(array));}}Netty解碼繼承MessageToMessageDecoder,他負責將ByteBuffer類型的數據解碼成Object對象。首先從數據報arg1中獲取需要解碼的byte數組,然后調用MessagePacke的read方法將其反序列化為Object對象,將解碼的對象加入到解碼列表arg2中,這樣就完成了MessagePack解碼工作。
3. 利用LengthFieldBasedFrameDecoder解決TCP粘包/拆包
對于TCP粘包 拆包問題來說,最常用的在消息頭中新增報文長度字段,然后利用該字段進行半包的編解碼。下面我們就利用Netty提供的LengthFieldBasedFrameDecoder和LengthFieldPrepender結合新開發的Netty編解碼器來實現對TCP粘包/拆包的支持。
EventLoopGroup group=new NioEventLoopGroup();try{Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000).handler(new ChannelInitializer<SocketChannel>(){@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//LengthFieldBasedFrameDecoder用于處理半包消息//這樣后面的MsgpackDecoder接收的永遠是整包消息ch.pipeline().addLast("frameDecoder",new LengthFieldBasedFrameDecoder(65535,0,2,0,2));ch.pipeline().addLast("msgpack decoder",new MsgPackDecoder());//在ByteBuf之前增加2個字節的消息長度字段ch.pipeline().addLast("frameEncoder",new LengthFieldPrepender(2)); ch.pipeline().addLast("msgpack encoder",new MsgpackEncoder());ch.pipeline().addLast(new EchoClientHandler(sendNumber));}});ChannelFuture f= b.connect(host,port).sync();f.channel().closeFuture().sync();}在MessagePack編碼器之前增加LengthFieldPrepender,它將在ByteBuffer之前增加2個字節的消息長度字段,其原理如下:
在MessagePack解碼器之前增加LengthFieldBasedFrameDecoder,用于處理半包消息,這樣后面的MsgpackDecoder接受到的永遠是整包消息。它的工作原理如下:
LengthFieldBasedFrameDecoder構造函數參數列表如下:
* @param maxFrameLength* the maximum length of the frame. If the length of the frame is* greater than this value, {@link TooLongFrameException} will be* thrown.* @param lengthFieldOffset* the offset of the length field* @param lengthFieldLength* the length of the length field* @param lengthAdjustment* the compensation value to add to the value of the length field* @param initialBytesToStrip* the number of first bytes to strip out from the decoded frame總結
以上是生活随笔為你收集整理的Netty详解(七):Netty 编解码以及消息头编解码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty详解(四):Netty 整体架
- 下一篇: 计算机网络:详解HTTP协议