文档章节

Netty之Codec的Decoders和Encoders概述

秋风醉了
 秋风醉了
发布于 2014/06/22 17:25
字数 1662
阅读 3914
收藏 4
点赞 0
评论 2

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===========

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 223
博文 581
码字总数 411013
作品 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

学习WebSocket(三) — 发送和接收Java对象

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

杰克鹏仔 ⋅ 2016/11/09 ⋅ 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 ⋅ 1

3.WebSocket编程—发送与接收JAVA对象

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

巧乐兹 ⋅ 2016/10/30 ⋅ 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

Kodi 15.0 Isengard RC 2 发布

Kodi 15.0 Isengard RC 2 发布,此版本现已提供在 Google Play,官方下载。 此版本相比 RC 1 改进如下: • Fix endless loop in PVR section which causes high CPU load • Fix crash on o......

oschina ⋅ 2015/07/12 ⋅ 0

[学习开发板]iTOP-4412开发板AVIN驱动配置

本文转自:http://www.topeetboard.com 平台:iTOP-4412开发板[学习开发板] 本文学习开发板AVIN模块的驱动配置 在内核目录下执行命令“make menuconfig” ,如下图: 将会打开内核的配置界面,...

歌之王子殿下 ⋅ 2016/03/22 ⋅ 0

第三章:Netty核心概念

这一章我们将讨论Netty的10个核心类。 Bootstrap ServerBootstrap EventLoop EventLoopGroup ChannelPipeline Channel Future ChannelFuture ChannelInitializer ChannelHandler 1.Crash Co......

李矮矮 ⋅ 2016/09/23 ⋅ 0

Netty 4.1.8 io.netty.util.ResourceLeakDetector - LEAK:

源代码及项目:https://github.com/zhouhailin555/NettyProtocol.git 希望各位大拿帮忙看看。 运行时报错如下: 1.ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was......

zhouhl ⋅ 2017/02/19 ⋅ 0

HandBrake 0.9.6 发布,视频转码工具

HandBrake 是一款开源、GPL 授权、跨平台、多线程的 DVD 到 MPEG-4 转换工具,现可用于 MacOS X、Linux 和 Windows 系统。 HandBrake 支持任意类型的 DVD 源,如 VIDEO_TS 文件夹、DVD 映像文...

红薯 ⋅ 2012/02/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 39分钟前 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部