文档章节

Netty之Codec的Decoders和Encoders概述

秋风醉了
 秋风醉了
发布于 2014/06/22 17:25
字数 1662
阅读 4203
收藏 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===========

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 239
博文 572
码字总数 416654
作品 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
学习WebSocket(三) — 发送和接收Java对象

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

杰克鹏仔
2016/11/09
39
1
Apache Commons Codec:各种加密了解一下

简介 Apache Commons Codec: Apache Commons Codec (TM) software provides implementations of common encoders and decoders such as Base64, Hex, Phonetic and URLs. Apache Commons Cod......

aboyliupu
11/15
0
0
3.WebSocket编程—发送与接收JAVA对象

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

巧乐兹
2016/10/30
774
1
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.3K
1

没有更多内容

加载失败,请刷新页面

加载更多

EOS docker开发环境

使用eos docker镜像是部署本地EOS开发环境的最轻松愉快的方法。使用官方提供的eos docker镜像,你可以快速建立一个eos开发环境,可以迅速启动开发节点和钱包服务器、创建账户、编写智能合约....

汇智网教程
今天
8
0
《唐史原来超有趣》的读后感优秀范文3700字

《唐史原来超有趣》的读后感优秀范文3700字: 作者:花若离。我今天分享的内容《唐史原来超有趣》这本书的读后感,我将这本书看了一遍之后就束之高阁了,不过里面的内容一直在在脑海中回放,...

原创小博客
今天
14
0
IC-CAD Methodology知识图谱

CAD (Computer Aided Design),计算机辅助设计,指利用计算机及其图形设备帮助设计人员进行设计工作,这个定义同样可以用来近似描述IC公司CAD工程师这个岗位的工作。 早期IC公司的CAD岗位最初...

李艳青1987
今天
14
0
CompletableFuture get方法一直阻塞或抛出TimeoutException

问题描述 最近刚刚上线的服务突然抛出大量的TimeoutException,查询后发现是使用了CompletableFuture,并且在执行future.get(5, TimeUnit.SECONDS);时抛出了TimeoutException异常,导致接口响...

xiaolyuh
今天
8
0
dubbo 搭建与使用

官网:http://dubbo.apache.org/en-us/ 一,安装监控中心(可以不安装) admin管理控制台,monitor监控中心 下载 bubbo ops 这个是新版的,需要node.js环境,我没有就用老版的了...

小兵胖胖
今天
16
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部