文档章节

Netty之Codec的Decoders和Encoders概述

秋风醉了
 秋风醉了
发布于 2014/06/22 17:25
字数 1662
阅读 4030
收藏 4

Netty之Codec的Decoders和Encoders概述

 A codec is made up of two parts: 

  • Decoder 

  • Encoder 

This  should  make  it  clear  that  the  decoder  is  for  inbound  and  the  encoder  is  for  outbound data. 


Decoder(解码器)

Netty provides a rich set of abstract base classes that help you easily write decoders. These are divided into different types: 

  • Decoders that decode from bytes to message(把字节解码为消息) 

  • Decoders that decode from message to message(把消息解码为另一种格式的消息) 

  • Decoders that decode from message to bytes(把消息解码为字节) 

Let s  define  what  the decoder s responsibility(责任) is. A decoder is responsible for decoding inbound data from one format to  another  one.  Because  a  decoder handles  inbound  data,  it s  an  abstract  implementation  of ChannelInboundHandler. 


>>ByteToMessageDecoder>>

ByteToMessageDecoder中抽象方法decode()

    /**
     * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
     * {@link ByteBuf} has nothing to read anymore, till nothing was read from the input {@link ByteBuf} or till
     * this method returns {@code null}.
     *
     * @param ctx           the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
     * @param in            the {@link ByteBuf} from which to read data
     * @param out           the {@link List} to which decoded messages should be added

     * @throws Exception    is thrown if an error accour
     */
    protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;

Often you want to decode from bytes to messages or even from bytes to another sequence of bytes. This is such a common task that Netty ship an abstract base class that you can use to do this. Exactly for this use case ByteToMessageDecoderis provided. It s an abstract base class that lets you write decoders that decode bytes into objects (POJOs) in an easy fashion.

Methods of ByteToMessageDecoder  

  1. decode() :The decode() method is the only abstract method you need to implement. It s called with a ByteBuf that holds all the received bytes and a List into which decoded messages should be added. The decode() method is called as long as it decodes something. 

  2. decodeLast() :Default implementation delegates to decode(). This method is called once, which is when the Channel goes inactive. If you need special handling here you may override decodeLast() to implement it. 

Let s  imagine  we  have  a  stream  of  bytes  written  from  a  remote  peer  to  us,  and  that  it contains  simple  integers.  We  want to  handle  each  integer separately later in  the ChannelPipeline,  so  we  want  to  read  the  integers  from  the  inbound ByteBuf and  pass each integer separately(分别的) to the next ChannelInboundHandler in the ChannelPipeline. 

You  see  in  figure  7.2  that  it  will  read  bytes  from  the  inbound  ByteBuf of  the ToIntegerDecoder, decode them, and write the decoded messages (int this case Integer) to the next ChannelInboundHandler in the ChannelPipeline. The figure also shows each integer will take up four bytes in the ByteBuf. 

package codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * 把字节转换为int
 * 继承抽象类ByteToMessageDecoder实现解码器
 */
public class ToIntegerDecoder extends ByteToMessageDecoder {

    @Override
    public void decode(ChannelHandlerContext ctx, ByteBuf in,
                       List<Object> out) throws Exception {
        if (in.readableBytes() >= 4) {  // Check if there are at least 4 bytes readable
            out.add(in.readInt());      //Read integer from inbound ByteBuf, add to the List of decodec messages
        }
    }
}


>>MessageToMessageDecoder>>

MessageToMessageDecoder中抽象方法decode()

    /**
     * Decode from one message to an other. This method will be called for each written message that can be handled
     * by this encoder.
     *
     * @param ctx           the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to
     * @param msg           the message to decode to an other one
     * @param out           the {@link List} to which decoded messages should be added
     * @throws Exception    is thrown if an error accour
     */
    protected abstract void decode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;

Methods of MessageToMessageDecoder 

decode() :The decode()method is the only abstract method you need to implement. It s called for each inbound message of the decoder and lets you decode the message in an other message format . The decoded messages are then passed t o the next ChannelInboundHandlerin the ChannelPipeline.

decodeLast() :Default implementation delegates to decode(). decodeLast()is only called one time, which is when the Channelgoes inactive. If you need special handling here you may override decodeLast()to implement it. 

If you want to decode a message to another type of message,MessageToMessageDecoderis the easiest way to go. The semantic(语义) is quite the same as for all the other decoders I explained before. 

To  illustrate(说明)  some  uses  let  me  give  you  an  example.  Imagine  you  have  integers  and  need  to convert  them  to  a string.  This  should  be  done  as  part  of the ChannelPipeline and implemented as a separate decoder to make it as flexible(灵活) and reusable(可复用的) as possible. 


Figure 7.3 shows the actual logic of the class I want to implement.

As it operates on messages and not bytes (in fact, a message can also be of type bytes). The inbound  message  is  directly  passed  in  the  decode()  method  and decoded  messages  will  be added to the List of decoded messages. So the decoder will receive inbound messages, decode them, and add them to the List of decoded  messages.  Once  done  it  will  forward  all  decoded  messages  to  the  next ChannelInboundHandlerin the ChannelPipeline.

该解码器的示例在我的demo中没有成功使用。

看我的demo在http://my.oschina.net/xinxingegeya/blog/282987

package codec;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;

import java.util.List;

public class IntegerToStringDecoder extends MessageToMessageDecoder<Integer> {

    @Override
    public void decode(ChannelHandlerContext ctx, Integer msg,
                       List<Object> out) throws Exception {
        out.add(String.valueOf(msg));
    }
}


Encoder(编码器)

As  a  counterpart  to  the  decoders  Netty  offers,  base  classes  help  you  to  write  encoders  in  an easy way. Again, these are divided into different types: 


Encoders that encode from message to message(把消息编码为消息) 


Encoders that encode from message to bytes(把消息编码为字节)


Before going deeper, let s define the responsibility of an encoder. An encoder is responsible for encoding outbound data from one format to another. As an encoder handles outbound data, it implements ChanneOutboundHandler. 


>>MessageToByteEncoder>>

MessageToByteEncoder中抽象方法encode()

    /**
     * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled
     * by this encoder.
     *
     * @param ctx           the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to
     * @param msg           the message to encode
     * @param out           the {@link ByteBuf} into which the encoded message will be written
     * @throws Exception    is thrown if an error accour
     */
    protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;

MessageToByteEncoder is  provided  to  serve  as  an  abstract  base  class  for  your  encoder implementations that need to transform messages back into bytes. 


shows the exact method you need to implement for your encoder, which is named encode. 

Methods of MessageToByteEncoder 

encode() :The encode()method is the only abstract method you need to implement. It s called with the outbound message, which was received by this encoder and encodes it in a ByteBuf. The ByteBufis then forwarded to the next ChannelOutboundHandlerin the ChannelPipeline. 

Let s see it in action to better understand its usage. I ve written single short values and want to encode them into a ByteBuf to finally send them over the wire. IntegerToByteEncoder is the implementation that s used for this purpose. 


Figure 7.5 shows the logic. 

Figure 7.5 shows that it will receive short messages, encode, and write to a ByteBuf. This ByteBuf  is  then  forwarded  to  the  next ChannelOutboundHandler in the ChannelPipeline. As you can also see in figure 7.5, every short will take up 2 bytes in the ByteBuf. 

package codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class IntegerToByteEncoder extends MessageToByteEncoder<Short> {
    @Override
    public void encode(ChannelHandlerContext ctx, Short msg, ByteBuf out)
            throws Exception {
        out.writeShort(msg);
    }
}


>>MessageToMessageEncoder>>

MessageToMessageEncoder中抽象方法encode()

    /**
     * Encode from one message to an other. This method will be called for each written message that can be handled
     * by this encoder.
     *
     * @param ctx           the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to
     * @param msg           the message to encode to an other one
     * @param out           the {@link List} into which the encoded msg should be added
     *                      needs to do some kind of aggragation
     * @throws Exception    is thrown if an error accour
     */
    protected abstract void encode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;

Suppose you need a way to encode from one message to another, similar to what you did for inbound data with MessageToMessageDecoder. MessageToMessageEncoder fills  this  gap. 


Shows  the  method  you  need  to implement for your encoder, which is named encode. 

Methods of MessageToMessageEncoder 

encode() :The encode()method is the only abstract method you need to implement. It s called for each message written with write( ) and encode the message to one or multiple new messages. The encoded messages are then forwarded to the next ChannelOutboundHandler in the ChannelPipeline. 

Again let us look at some example. Imaging you need to encode Integer messages to String messages you could do this easily with MessageToMessageEncoder. 


Figure 7.6 shows the logic. 

The  encoder  encode  Integer  messages  and  forward  them  to  the  next ChannelOutboundHandlerin the ChannelPipeline. 

下面这个编码器在一个demo中我试过,demo没运行成功。看这篇文章http://my.oschina.net/xinxingegeya/blog/282987。原来使用

package codec;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;

import java.util.List;

public class IntegerToStringEncoder extends MessageToMessageEncoder<Integer> {
    @Override
    public void encode(ChannelHandlerContext ctx, Integer msg,
                       List<Object> out) throws Exception {
        out.add(String.valueOf(msg));
    }
}

===========END===========

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 232
博文 574
码字总数 405033
作品 0
朝阳
程序员
加载中

评论(2)

秋风醉了
秋风醉了

引用来自“BoXuan”的评论

不错
抬举了,就是整理了一下资料,英语水平有限,不能翻译成中文。其实原文还是很好读的,没有多少生词和复杂的句式。
节节草
节节草
不错
MQTT---HiveMQ源码详解(九)Netty-Codec

源博客地址:http://blog.csdn.net/pipinet123 MQTT交流群:221405150 codec无外乎就是encoder和decoder,无外乎就是把客户端发过来的mqtt字节码转换成mqtt消息的对象,把服务端发出去的mqtt对...

pipinet123
2017/03/10
0
0
Kodi 15.0 Isengard RC 1 发布

Kodi 15.0 Isengard RC 1 发布,此版本现已提供在 Google Play,替代之前第一个版本 14.2,主要是支持更多的现代化 Android 设备特性,比如平板上支持 Nexus Player 和 NVIDIA Shield Androi...

oschina
2015/07/03
3.2K
1
学习WebSocket(三) — 发送和接收Java对象

被@OnMessage修饰的函数是用来接收和返回客户端发送过来的消息的,接收的参数和返回值可以为Java对象。 要使@OnMessage修饰的函数可以处理Java对象,需要对端点类设置decoders和encoders,其...

杰克鹏仔
2016/11/09
39
1
3.WebSocket编程—发送与接收JAVA对象

发送与接收JAVA对象 被@OnMessage修饰的函数是用来接收和返回客户端发送过来的消息的,接收的参数和返回值可以为Java对象。 要使@OnMessage修饰的函数可以处理Java对象,需要对端点类设置dec...

巧乐兹
2016/10/30
774
1
Netty in Action ——— The codec framework

本文是Netty文集中“Netty in action”系列的文章。主要是对Norman Maurer and Marvin Allen Wolfthal 的 《Netty in action》一书简要翻译,同时对重要点加上一些自己补充和扩展。 本章含盖...

tomas家的小拨浪鼓
2017/12/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
1
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
1
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
3
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部