Netty 学习(三):通信协议和编解码

作者: Grey

原文地址:

博客园:Netty 学习(三):通信协议和编解码

CSDN:Netty 学习(三):通信协议和编解码

无论使用 Netty 还是原生 Socket 编程,都可以实现自定义的通信协议。

所谓协议就是:客户端和服务端商量好,每一个二进制数据包中的每一段字节分别代表什么含义的规则。

有了规则,在服务端和客户端就可以通过这个设置好的规则进行二进制和对象的转换。

通信协议格式可以参考如下格式

每个部分的说明如下

魔数:用来标识这个数据包是否遵循我们设计的通信协议,类似 Java 字节码开头的4字节:0xcafebabe

版本标识:用来标识这个协议是什么版本,用于后续协议的升级

序列化算法:用于标识这个协议的数据包使用什么序列化算法,比如:JSON,XML等

指令:用于标识这个数据在收到后应该使用什么处理逻辑。

数据长度&数据内容:不赘述

定好格式以后,

接下来我们可以约定双方的序列化方法,这里我们可以用 JSON 序列化/反序列化 为例,其他格式的类似。

使用 Gson 可以很方便将 JSON 字符串和对象进行互转:

    private static final Gson gson = new Gson();
// 序列化
public byte[] serialize(Object object) {
return gson.toJson(object).getBytes(UTF_8);
}
// 反序列化
public <T> T deserialize(Class<T> clazz, byte[] bytes) {
return gson.fromJson(new String(bytes, UTF_8), clazz);
}

实现了对象和字节数组的互转以后,我们需要实现字节数组和 Netty 通信载体 ByteBuf 的互转,包括如下两个方法

ByteBuf 编码(数据包)

上述编码方法需要做如下几个事情

  1. 分配 ByteBuf (分配一块内存区域,Netty 会直接创建一个堆外内存)

  2. 按照协议获取数据包对应的内容

  3. 严格按照协议规定的字节数填充到 ByteBuf 中

数据包 解码(ByteBuf byteBuf)

上述解码方法主要做如下几件事情

  1. 校验魔数

  2. 校验版本号

  3. 如果严格按照规范传输的 ByteBuf,上述两步校验一定是通过的,可以直接跳过。

  4. 获取序列化算法,指令和数据包长度,并将数据内容转换成字节数组

  5. 将字节数组转换成对应的数据包对象。

因为不同的数据包内容有所不一样,所以应该设置一个抽象类,由各个子类实现具体数据包的内容。

package protocol;

import lombok.Data;

/**
* 数据包抽象类
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/15
* @since
*/
@Data
public abstract class Packet {
/**
* 协议版本
*/
private Byte version = 1; /**
* 指令,由子类实现
*
* @return
*/
public abstract Byte getCommand();
}

对于一个具体的操作,比如登录操作,它需要的数据包需要继承并实现这个抽象类的抽象方法。

package protocol;

import lombok.Data;

import static protocol.Command.LOGIN_REQUEST;

/**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/15
* @since
*/
@Data
public class LoginRequestPacket extends Packet {
// 登录操作需要的数据内容包括如下三个
private Integer userId;
private String username;
private String password; @Override
public Byte getCommand() {
return LOGIN_REQUEST;
}
}

对于调用者来说,只需要使用LoginRequestPacket即可,无须关注其底层的编码和解码工作。伪代码如下

func() {
LoginRequestPacket loginRequestPacket = new LoginRequestPacket();
loginRequestPacket.setVersion(((byte) 1));
loginRequestPacket.setUserId(123);
loginRequestPacket.setUsername("zhangsan");
loginRequestPacket.setPassword("password");
// 编码
ByteBuf byteBuf = 封装好的编解码工具类.编码(loginRequestPacket);
// 解码
Packet decodedPacket = 封装好的编解码工具类.解码(byteBuf);
// 序列化成我们需要的对象
序列化和反序列化工具类.序列化(decodedPacket);
}

完整代码见:hello-netty

本文所有图例见:processon: Netty学习笔记

更多内容见:Netty专栏

参考资料

跟闪电侠学 Netty:Netty 即时聊天实战与底层原理

深度解析Netty源码

Netty 学习(三):通信协议和编解码的更多相关文章

  1. Netty游戏服务器之四protobuf编解码和黏包处理

    我们还没讲客户端怎么向服务器发送消息,服务器怎么接受消息. 在讲这个之前我们先要了解一点就是tcp底层存在粘包和拆包的机制,所以我们在进行消息传递的时候要考虑这个问题. 看了netty权威这里处理的办 ...

  2. Netty学习三:线程模型

    1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...

  3. FFmpeg 学习(五):FFmpeg 编解码 API 分析

    在上一篇文章 FFmpeg学习(四):FFmpeg API 介绍与通用 API 分析 中,我们简单的讲解了一下FFmpeg 的API基本概念,并分析了一下通用API,本文我们将分析 FFmpeg 在编 ...

  4. Netty学习(三)-Netty重要接口讲解

    上一节我们写了一个HelloWorld,对于Netty的运行有了一定的了解,知道Netty是如何启动客户端和服务器端.这一节我们简要的讲解一下几个重要的接口,初步探讨Netty的运行机制,当然刚学Ne ...

  5. Netty学习(三)高性能之ByteBuf源码解析

    原文链接: https://juejin.im/post/5db8ea506fb9a02061399ab3 Netty 的 ByteBuf 类型 Pooled(池化).Unpooled(非池化) Di ...

  6. 【转】Netty系列之Netty编解码框架分析

    http://www.infoq.com/cn/articles/netty-codec-framework-analyse/ 1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称 ...

  7. Netty系列之Netty编解码框架分析

    1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...

  8. Netty 编解码技术 数据通信和心跳监控案例

    Netty 编解码技术 数据通信和心跳监控案例 多台服务器之间在进行跨进程服务调用时,需要使用特定的编解码技术,对需要进行网络传输的对象做编码和解码操作,以便完成远程调用.Netty提供了完善,易扩展 ...

  9. RocketMq通信协议格式及编解码 (源码分析)

    一.RocketMq broker服务器与客户端的网络通信是基于netty4.x实现的,重点分析  RocketMq设计的通信协议及对应的编解码 开发.         名字解释           ...

随机推荐

  1. docker的平替--podman

    前言 我们都知道,docker这个东西,是CaaS(Container as a Service,容器即服务)的通常解法.我们使用docker来管理容器的生命周期,比如镜像的生成.容器的管理和定制(D ...

  2. Metasploit(msf)利用ms17_010(永恒之蓝)出现Encoding::UndefinedConversionError问题

    Metasploit利用ms17_010(永恒之蓝) 利用流程 先确保目标靶机和kali处于同一网段,可以互相Ping通 目标靶机防火墙关闭,开启了445端口 输入search ms17_010 搜索 ...

  3. 数学工具类Math

    概述 java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数.对数.平方根和三角函数.类似这样的工具 类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单 基本运算的方法 ...

  4. HelloWord程序代码的编写和HelloWord程序的编译运行

    1.新建文件夹,存放代码 2.新建一个Java文件 文件后缀名.java(Hello.java) 3.编写代码public class Hello{public static void main(St ...

  5. 关于 Flink 状态与容错机制

    Flink 作为新一代基于事件流的.真正意义上的流批一体的大数据处理引擎,正在逐渐得到广大开发者们的青睐.就从我自身的视角看,最近也是在数据团队把一些原本由 Flume.SparkStreaming. ...

  6. Mac平台下git命令自动补全

    一.安装bash-completion 安装Homebrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com ...

  7. Python语言之面向对象

    Python语言之面向对象 前言 面向对象 -- Object Oriented 简写:OO 面向对象设计 -- Object Oriented Design 简写:OOD 面向对象编程 -- Obj ...

  8. 部署yum仓库

    YUM介绍 YUM(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器. 基于RPM包管理,能够从指定的 ...

  9. 【Codeforces1706A】 Another String Minimization Problem

    官方标签 贪心.字符串 题目描述 输入 输出 样例输入 6 4 5 1 1 3 1 1 5 2 4 1 1 1 1 1 2 4 1 3 2 7 7 5 4 5 5 5 3 5 样例输出 ABABA B ...

  10. VS Code + GitHub

    来到博客园学着别人美化了一下自己的博客页面,蛮好看的,然后右上角有一个"Fork me on GitHub".之前就因为好奇而注册过GitHub,但一直不会使,现在正式开始编程学习 ...