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设计的通信协议及对应的编解码 开发. 名字解释 ...
随机推荐
- JDBC:处理事务
1.如何实现事务 如果现在希望对 A 表和 B 表同时删除某一个 id 号的记录,使这两个sql操作组成一个事务.(成功则同时成功,否则都失败) 注意:如果 B 表 建立了引用 A 表的id外键,并指 ...
- Unity3D学习笔记7——GPU实例化(2)
目录 1. 概述 2. 详论 2.1. 实现 2.2. 解析 3. 参考 1. 概述 在上一篇文章<Unity3D学习笔记6--GPU实例化(1)>详细介绍了Unity3d中GPU实例化的 ...
- 从入门到爱上Git
时间不在于你拥有多少,而在于你怎样使用------时之沙 · 艾克 一.Git设置 1.1 Git全局设置 当我们安装好Git以后,我们需要对Git进行账号.邮箱的设置 设置用户信息 git conf ...
- 地址解析协议(ARP) 分析
什么是ARP协议 ARP(A ddress R esolution P rotocol)- 地址解析协议 ,用于将IP地址解析为MAC地址.复杂来说,ARP用于32位IPv4地址和以太网的48位MAC ...
- 零基础学Java(10)面向对象-使用LocalDate类完成日历设计
前言 在我们完成这个日历设计前,需要了解Java中的预定义类LocalDate的一些用法 语法 LocalDate.now() // 2022-07-01 会构造一个新对象,表示构造这个对象时的日期. ...
- Redis系列4:高可用之Sentinel(哨兵模式)
Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 1 背景 从第三篇 Redis系列3:高可用之主从架构 ,我们知道,为Re ...
- Spring 常见面试题总结 | JavaGuide
首发于 JavaGuide 在线网站:Spring 常见面试题总结 最近在对 JavaGuide 的内容进行重构完善,同步一下最新更新,希望能够帮助你. Spring 基础 什么是 Spring 框架 ...
- 远见而明察近观若明火|Centos7.6环境基于Prometheus和Grafana结合钉钉机器人打造全时监控(预警)Docker容器服务系统
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_181 我们知道,奉行长期主义的网络公司,势必应在软件开发流程管理体系上具备规范意识,即代码提交有CR(CodeReview),功能 ...
- 5.30 NOI 模拟
$5.30\ NOI $模拟 高三大哥最后一次模拟考了,祝他们好运 \(T1\)装箱游戏 显然可以将四种字母之间的空缺当做状态枚举 那么这道题就很显然了 #include<bits/stdc++ ...
- 不止跑路,拯救误操作rm -rf /*的小伙儿
摘要:误执行了 rm -rf /* 之后,除了跑路还能怎么办? 本文分享自华为云社区<拯救被 rm -rf 伤到的小伙>,作者:Gauss 松鼠会. 灵魂画师再次上线 在开饭前我们先了 ...