Netty 源码深度解析(九) - 编码(上)

概述

一个问题
Netty 源码深度解析(九) - 编码(上)

编码器实现了ChannelOutboundHandler,并将出站数据从 一种格式转换为另一种格式,和我们方才学习的解码器的功能正好相反。Netty 提供了一组类, 用于帮助你编写具有以下功能的编码器:

  • 将消息编码为字节
  • 将消息编码为消息
    我们将首先从抽象基类 MessageToByteEncoder 开始来对这些类进行考察

1 抽象类 MessageToByteEncoder

Netty 源码深度解析(九) - 编码(上)

解码器通常需要在Channel关闭之后产生最后一个消息(因此也就有了 decodeLast()方法)

这显然不适于编码器的场景——在连接被关闭之后仍然产生一个消息是毫无意义的


1.1 ShortToByteEncoder


其接受一Short 型实例作为消息,编码为Short的原子类型值,并写入ByteBuf,随后转发给ChannelPipeline中的下一个 ChannelOutboundHandler

每个传出的 Short 值都将会占用 ByteBuf 中的 2 字节

Netty 源码深度解析(九) - 编码(上)


Netty 源码深度解析(九) - 编码(上)

1.2 Encoder

Netty 源码深度解析(九) - 编码(上)


Netty 提供了一些专门化的 MessageToByteEncoder,可基于此实现自己的编码器

WebSocket08FrameEncoder类提供了一个很好的实例


Netty 源码深度解析(九) - 编码(上)


2 抽象类 MessageToMessageEncoder


你已经看到了如何将入站数据从一种消息格式解码为另一种

为了完善这幅图,将展示 对于出站数据将如何从一种消息编码为另一种。MessageToMessageEncoder类的 encode()方法提供了这种能力

Netty 源码深度解析(九) - 编码(上)


为了演示,使用IntegerToStringEncoder 扩展了 MessageToMessageEncoder

  • 编码器将每个出站 Integer 的 String 表示添加到了该 List 中


Netty 源码深度解析(九) - 编码(上)
Netty 源码深度解析(九) - 编码(上)关于有趣的 MessageToMessageEncoder 的专业用法,请查看 io.netty.handler. codec.protobuf.ProtobufEncoder类,它处理了由 Google 的 Protocol Buffers 规范所定义 的数据格式。


一个java对象最后是如何转变成字节流,写到socket缓冲区中去的

writeAndFlush


  • 从tail节点开始往前传播
  • 逐个调用channelHandler#write
  • 逐个调用channelHandler#flush

java对象编码过程

write:写队列

flush:刷新写队列

writeAndFlush: 写队列并刷新


pipeline中的标准链表结构

Netty 源码深度解析(九) - 编码(上)


数据从head节点流入,先拆包,然后解码成业务对象,最后经过业务Handler处理,调用write,将结果对象写出去

而写的过程先通过tail节点,然后通过encoder节点将对象编码成ByteBuf,最后将该ByteBuf对象传递到head节点,调用底层的Unsafe写到JDK底层管道


Java对象编码过程

为什么我们在pipeline中添加了encoder节点,java对象就转换成netty可以处理的ByteBuf,写到管道里?

我们先看下调用write的code

Netty 源码深度解析(九) - 编码(上)


业务处理器接受到请求之后,做一些业务处理,返回一个user

  • 然后,user在pipeline中传递

Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

情形一

Netty 源码深度解析(九) - 编码(上)
Netty 源码深度解析(九) - 编码(上)

情形二


Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

Netty 源码深度解析(九) - 编码(上)

handler 如果不覆盖 flush 方法,就会一直向前传递直到 head 节点

Netty 源码深度解析(九) - 编码(上)


落到 Encoder节点,下面是 Encoder 的处理流程


Netty 源码深度解析(九) - 编码(上)

按照简单自定义协议,将Java对象 User 写到传入的参数 out中,这个out到底是什么?

需知User对象,从BizHandler传入到 MessageToByteEncoder时,首先传到 write

Netty 源码深度解析(九) - 编码(上)


上一篇:spring boot 中对修改的头像进行更改,同时删除原来的头像,头像是初始头像不删除,信息保存session,实时更新


下一篇:SpringMVC小记(一)