Netty 学习(三):通信协议和编解码
Netty 学习(三):通信协议和编解码
作者: Grey
原文地址:
无论使用 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 编码(数据包)
上述编码方法需要做如下几个事情
分配 ByteBuf (分配一块内存区域,Netty 会直接创建一个堆外内存)
按照协议获取数据包对应的内容
严格按照协议规定的字节数填充到 ByteBuf 中
数据包 解码(ByteBuf byteBuf)
上述解码方法主要做如下几件事情
校验魔数
校验版本号
如果严格按照规范传输的 ByteBuf,上述两步校验一定是通过的,可以直接跳过。
获取序列化算法,指令和数据包长度,并将数据内容转换成字节数组
将字节数组转换成对应的数据包对象。
因为不同的数据包内容有所不一样,所以应该设置一个抽象类,由各个子类实现具体数据包的内容。
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游戏服务器之四protobuf编解码和黏包处理
我们还没讲客户端怎么向服务器发送消息,服务器怎么接受消息. 在讲这个之前我们先要了解一点就是tcp底层存在粘包和拆包的机制,所以我们在进行消息传递的时候要考虑这个问题. 看了netty权威这里处理的办 ...
- Netty学习三:线程模型
1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...
- FFmpeg 学习(五):FFmpeg 编解码 API 分析
在上一篇文章 FFmpeg学习(四):FFmpeg API 介绍与通用 API 分析 中,我们简单的讲解了一下FFmpeg 的API基本概念,并分析了一下通用API,本文我们将分析 FFmpeg 在编 ...
- Netty学习(三)-Netty重要接口讲解
上一节我们写了一个HelloWorld,对于Netty的运行有了一定的了解,知道Netty是如何启动客户端和服务器端.这一节我们简要的讲解一下几个重要的接口,初步探讨Netty的运行机制,当然刚学Ne ...
- Netty学习(三)高性能之ByteBuf源码解析
原文链接: https://juejin.im/post/5db8ea506fb9a02061399ab3 Netty 的 ByteBuf 类型 Pooled(池化).Unpooled(非池化) Di ...
- 【转】Netty系列之Netty编解码框架分析
http://www.infoq.com/cn/articles/netty-codec-framework-analyse/ 1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称 ...
- Netty系列之Netty编解码框架分析
1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...
- Netty 编解码技术 数据通信和心跳监控案例
Netty 编解码技术 数据通信和心跳监控案例 多台服务器之间在进行跨进程服务调用时,需要使用特定的编解码技术,对需要进行网络传输的对象做编码和解码操作,以便完成远程调用.Netty提供了完善,易扩展 ...
- RocketMq通信协议格式及编解码 (源码分析)
一.RocketMq broker服务器与客户端的网络通信是基于netty4.x实现的,重点分析 RocketMq设计的通信协议及对应的编解码 开发. 名字解释 ...
随机推荐
- 全国30m精度二级分类土地利用数据
数据下载链接:数据下载链接 引言 全国土地利用数据产品是以Landsat TM/ETM/OLI遥感影像为主要数据源,经过影像融合.几何校正.图像增强与拼接等处理后,通过人机交互目视解译的方法,将全国 ...
- 集合容器和Hash表
集合容器 集合相当于一个容器,在我们使用Arraylist的时候添加参数相当与放了一个容器中.这里面的元素是可以重复的 在HashSet中添加元素是没有重复的,我们来写一个测试看一下 public s ...
- Python 内置logging 使用详细讲
logging 的主要作用 提供日志记录的接口和众多处理模块,供用户存储各种格式的日志,帮助调试程序或者记录程序运行过程中的输出信息. logging 日志等级 logging 日志等级分为五个等级, ...
- SVM简要介绍
SVM 支持向量机(SVM),是一个用于解决二分类问题的有监督机器学习模型. 1.SVM的两个优点 更高的速度 在有一定的样本数量支持下(成千上万张),具有比其他模型有更好的效果 2.SVM的工作过程 ...
- 5-9 Leaf 分布式ID
Leaf 什么Leaf leaf是叶子的意思 我们使用的Leaf是美团公司开源的一个分布式序列号(id)生成系统 我们可以在Github网站上下载项目直接使用 为什么需要Leaf 上面的图片中 是一个 ...
- 【前端面试】Vue面试题总结(持续更新中)
Vue面试题总结(持续更新中) 题目参考链接 https://blog.csdn.net/weixin_45257157/article/details/106215158 由于已经有很多前辈深造VU ...
- SpringMVC底层——请求参数处理流程描述
在DispatcherServlet.java的doDispatch方法中,springmvc通过handlermapping里面找哪个handler能处理请求,handler封装了目标方法的信息, ...
- Techempower web框架性能测试第21轮结果发布--asp.net core继续前进
废话不说,直接上结果: Round 21 results - TechEmpower Framework Benchmarks Techempower benchmark是包含范围最广泛的web框架性 ...
- ROS机械臂 Movelt 学习笔记3 | kinect360相机(v1)相关配置
目标是做一个机械臂视觉抓取的demo,在基地里翻箱倒柜,没有找到学长所说的 d435,倒是找到了一个老古董 kinect 360. 前几天就已经在旧电脑上配置好了,现在记录在新电脑上的配置过程. 1. ...
- word count的reduce过程以及项目打包部署
map过程已经写完了,上面那个流程我们涉及到了泛型以及序列化,我们要知道每个参数代表的含义,这样有助于我们理解整个流程. 下面我们开始reduce,这个过程我们要把map输出的键值对把key值相同的放 ...