【Netty】編解碼器

A minor發表於2020-12-31

當你通過 Netty 傳送或者接受一個訊息的時候,就將會發生一次資料轉換

  • 入站時 – 訊息被解碼(Decode):從位元組(二進位制)轉換為我們能讀懂並操作的格式(int、String、Java物件…)
  • 出站時 – 訊息被編碼(Encode):從我們能讀懂並操作的格式的形式(int、String、Java物件…)轉換為位元組形式(二進位制)

Netty 提供了一系列實用的編碼解碼器,比如編解碼字串的 StringEncoder 和 StringDecoder,編解碼物件的 ObjectEncoder 和ObjectDecoder 等,他們都實現了 ChannelInboundHadnler 或者 ChannelOutcoundHandler 介面。

在這裡插入圖片描述

在這些類中, channelRead 方法已經被重寫了。以入站為例,對於每個從入站 Channel 讀取的訊息,這個方法會被呼叫。隨後,它將呼叫由已知解碼器所提供的 decode() 方法進行解碼,並將已經解碼的位元組轉發給 ChannelPipeline 中的下一個 ChannelInboundHandler。

除了 Netty 已經實現的,我們也可以通過整合 MessageToByteEncoder,ByteToMessageDecoder 自定義編解碼器。

【Netty】編解碼器
/*
* 自定義編碼器
* 實現 MessageToByteEncoder介面,重寫 encode 方法
* 注:通過泛型指定可以編碼資料型別
*/
public class LongToByteEncoder extends MessageToByteEncoder<Long> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Long msg, ByteBuf out) throws Exception {
        System.out.println("LongToByteEncoder encode被呼叫");
        System.out.println("msg=" + msg);
        // 關鍵!!將編碼結果通過 pipeline 繼續向下傳遞,繼續接受處理
        out.writeLong(msg);
    }
}
/*
* 自定義解碼器
* 實現 ByteToMessageDecoder 介面,重寫 decode 方法
*/
public class ByteToLongDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("ByteToLongDecoder decode 被呼叫");
        // 注:因為 long 8個位元組, 需要判斷有8個位元組,才能讀取一個long
        if(in.readableBytes() >= 8) {
        	// 關鍵!!將解碼結果通過 pipeline 繼續向下傳遞,繼續接受處理
            out.add(in.readLong());
        }
    }
}

然後再將我們的自定義編解碼器加入到 ChannelPipeline 中

public class NettyServerInitailizer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) {

        ChannelPipeline pipeline = socketChannel.pipeline();
		// 入站-Decode
		pipeline.addLast(new ByteToLongDecoder());
		// 出棧-Encode
		pipeline.addLast(new LongToByteEncoder());
		// 自定義的 Handler
		pipeline.addLast(new NettyServerHandler());
    }
}

相關文章