Netty系列-Netty编解码机制

在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码。

Netty提供了强大的编解码器框架,使得我们编写自定义的编解码器很容易,也容易封装重用。对于Netty而言,编解码器由两部分组成:编码器、解码器。

  1. 解码器:负责将消息从字节或其他序列形式转成指定的消息对象。
  2. 编码器:将消息对象转成字节或其他序列形式在网络上传输。

Netty 的编(解)码器实现了 ChannelHandlerAdapter,也是一种特殊的 ChannelHandler,所以依赖于 ChannelPipeline,可以将多个编(解)码器链接在一起,以实现复杂的转换逻辑。

Netty里面的编解码: 解码器:负责处理"入站 InboundHandler数据" 编码器:负责"出站 OutboundHandler数据"。

# Protobuf编解码

Protobuf 是 Google 发布的开源项目,全称 Google Protocol Buffers,是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC[远程过程调用 remote procedure call ] 数据交换格式。目前很多公司 http+json -> tcp+protobuf。

Protobuf 是以 message 的方式来管理数据的. 支持跨平台、跨语言,即[客户端和服务器端可以是不同的语言编写的] (支持目前绝大多数语言,例如 C++、C#、Java、python 等)

高性能,高可靠性。使用 protobuf 编译器能自动生成代码,Protobuf 是将类的定义使用.proto 文件进行描述。说明,在idea 中编写 .proto 文件时,会自动提示是否下载 .ptotot 编写插件. 可以让语法高亮。然后通过 protoc.exe 编译器根据.proto 自动生成.java 文件

# 使用protobuf

主要步骤:

  1. 在 .proto 文件中定义消息格式
  2. 使用 protobuf 编译器编译 .proto文件 成 Java 类
  3. 使用 Java 对应的 protobuf API来写或读消息

定义.proto 文件

//protobuf语法有 proto2和proto3两种,这里指定 proto3
syntax = "proto3"; 
// 文件选项
option java_package = "com.server.protocol.protobuf";
option java_outer_classname = "MessageBase";
// 消息模型定义
message Message {
    string requestId = 1;
    CommandType cmd = 2;
    string content = 3;
    enum CommandType {
        NORMAL = 0; //常规业务消息
        HEARTBEAT_REQUEST = 1; //客户端心跳消息
        HEARTBEAT_RESPONSE = 2; //服务端心跳消息
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

构建实体类

protoc -I = ./ --java_out=./ ./Message.proto
1
  • -I 选项用于指定待编译的 .proto消息定义文件所在的目录,该选项也可以写作为 --proto_path
  • --java_out选项表示生成 Java代码后存放位置,对于不同语言,我们的选项可能不同,比如生成C++代码为 --cpp_out
  • 在前两个选项后再加上 待编译的消息定义文件

使用实体类

参考官方文档 : https://developers.google.com/protocol-buffers/docs/proto

# protobuf的编解码器

名称 描述
ProtobufDecoder 使用 protobuf 对消息进行解码
ProtobufEncoder 使用 protobuf 对消息进行编码
ProtobufVarint32FrameDecoder 根据消息中的 Google Protocol Buffers 的 “Base 128 Varint" 整型长度字段值动态地分割所接收到的 ByteBuf
ProtobufVarint32LengthFieldPrepender 向 ByteBuf 前追加一个Google Protocol Buffers 的 “Base 128 Varint" 整型长度字段值

# 使用注意

ProtobufDecoder仅仅负责解码,它不支持读半包。因此,在 ProtobufDecoder 前面,一定要有能够处理读半包的解码器,有三种方式可以选择。使用Netty提供的 Protobufvarint32FrameDecoder,它可以处理半包消息:继承Netty提供的通用半包解码器 LengtFieldBasedFrameDecoder;继承 ByteToMessageDecoder 类,自己处理半包消息如果你只使用 ProtobufDecoder 解码器而忽略对半包消息的处理,程序是不能正常工作的。

上次更新: 2020/07/27, 13:07:00
最近更新
01
RabbitMQ简介
10-27
02
聊聊Java多态
10-21
03
JVM垃圾回收器
10-16
更多文章>