Netty自定义数据包

article/2025/10/8 7:29:12

自定义数据包

粘包现象:两个数据包连在一起,导致无法区分。
分包现象:一个数据包中的数据被间隔。
粘包和分包出现的原因是:没有一个稳定数据结构。

数据包的结构:
自定义数据包=包头+模块号+命令号+长度+数据
包头:4个字节
模块号:2个字节short,区分请求类型
命令号:2个字节short,区分具体请求
长度:4个字节,描述数据部分字节长度
数据:更加详细的信息

通过序列化方式将下列数据,转化成字节序列
包头:通常是一个固定的量,使数据更加稳定
自定义请求(响应)=模块号+命令号+请求数据部分

以使用Netty ChannelBuffer序列化为例
请求编码器

public class RequestEncoder extends OneToOneEncoder{
@Override
protected Object encode(ChannelHandlerContext context, Channel channel, Object rs) throws Exception {Request request = (Request)(rs);ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();//包头buffer.writeInt(ConstantValue.FLAG);//modulebuffer.writeShort(request.getModule());//cmdbuffer.writeShort(request.getCmd());//长度buffer.writeInt(request.getDataLength());//dataif(request.getData() != null){buffer.writeBytes(request.getData());}		return buffer;
}

}

请求解码器
frameDecoder协助解决粘包、分包问题

public class RequestDecoder extends FrameDecoder{/*** 数据包基本长度*/public static int BASE_LENTH = 4 + 2 + 2 + 4;
@Override
protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception {//可读长度必须大于基本长度if(buffer.readableBytes() >= BASE_LENTH){//防止socket字节流攻击if(buffer.readableBytes() > 2048){buffer.skipBytes(buffer.readableBytes());}//记录包头开始的indexint beginReader;while(true){beginReader = buffer.readerIndex();buffer.markReaderIndex();if(buffer.readInt() == ConstantValue.FLAG){break;}//未读到包头,略过一个字节buffer.resetReaderIndex();buffer.readByte();//长度又变得不满足if(buffer.readableBytes() < BASE_LENTH){return null;}}//模块号short module = buffer.readShort();//命令号short cmd = buffer.readShort();//长度int length = buffer.readInt();//判断请求数据包数据是否到齐if(buffer.readableBytes() < length){//还原读指针buffer.readerIndex(beginReader);return null;}//读取data数据byte[] data = new byte[length];buffer.readBytes(data);Request request = new Request();request.setModule(module);request.setCmd(cmd);request.setData(data);//继续往下传递 return request;}//数据包不完整,需要等待后面的包来return null;
}

}

结合Netty进行数据传递(选择自定义的报文结构)

客户端
pipeline.addLast(“decoder”, new ResponseDecoder()); 用来解析响应,addLast追加
pipeline.addLast(“encoder”, new RequestEncoder()); 用来编码请求
在request中定义数据时,可以继承使用PB的序列化方式,或者自定义的序列化方式 request.setData(fightRequest.getBytes());

public class Client {public static void main(String[] args) throws InterruptedException {//服务类ClientBootstrap bootstrap = new  ClientBootstrap();//线程池ExecutorService boss = Executors.newCachedThreadPool();ExecutorService worker = Executors.newCachedThreadPool();//socket工厂bootstrap.setFactory(new NioClientSocketChannelFactory(boss, worker));//管道工厂bootstrap.setPipelineFactory(new ChannelPipelineFactory() {@Overridepublic ChannelPipeline getPipeline() throws Exception {ChannelPipeline pipeline = Channels.pipeline();pipeline.addLast("decoder", new ResponseDecoder());pipeline.addLast("encoder", new RequestEncoder());pipeline.addLast("hiHandler", new HiHandler());return pipeline;}});//连接服务端ChannelFuture connect = bootstrap.connect(new InetSocketAddress("127.0.0.1", 10101));Channel channel = connect.sync().getChannel();System.out.println("client start");Scanner scanner = new Scanner(System.in);while(true){System.out.println("请输入");int fubenId = Integer.parseInt(scanner.nextLine());int count = Integer.parseInt(scanner.nextLine());FightRequest fightRequest = new FightRequest();fightRequest.setFubenId(fubenId);fightRequest.setCount(count);Request request = new Request();request.setModule((short) 1);request.setCmd((short) 1);request.setData(fightRequest.getBytes());//发送请求channel.write(request);}
}

}

服务器端
pipeline.addLast(“decoder”, new RequestDecoder()); 用来解析请求
pipeline.addLast(“encoder”, new ResponseEncoder()); 用来编码响应

public class Server {public static void main(String[] args) {//服务类ServerBootstrap bootstrap = new ServerBootstrap();//boss线程监听端口,worker线程负责数据读写ExecutorService boss = Executors.newCachedThreadPool();ExecutorService worker = Executors.newCachedThreadPool();//设置niosocket工厂bootstrap.setFactory(new NioServerSocketChannelFactory(boss, worker));//设置管道的工厂bootstrap.setPipelineFactory(new ChannelPipelineFactory() {@Overridepublic ChannelPipeline getPipeline() throws Exception {ChannelPipeline pipeline = Channels.pipeline();pipeline.addLast("decoder", new RequestDecoder());pipeline.addLast("encoder", new ResponseEncoder());pipeline.addLast("helloHandler", new HelloHandler());return pipeline;}});bootstrap.bind(new InetSocketAddress(10101));System.out.println("start!!!");}}

知识补充:
TCP数据包结构=偏移量+窗口字段+端口号,总共占32个字节
上面的自定义的最基础的占用12个字节
在这里插入图片描述

在这里插入图片描述


http://chatgpt.dhexx.cn/article/MqyMGbEW.shtml

相关文章

数据包知识

ARP 全称&#xff1a;Address Resolution Protocol 地址解析协议 ARP请求 数据包的目的地址是&#xff08;ff:ff:ff:ff:ff:ff&#xff09;&#xff0c;这是以太网中的广播地址&#xff0c; 所有发送到这个地址的数据包都会被广播到当前网段中的所有设备。这个数据 包中以太网…

数据帧和数据包解读

数据帧和数据包解读 文章目录 数据帧和数据包解读一、数据帧1.什么是数据帧2.数据帧的组成 二、数据包1.什么是数据包2.数据包的组成 一、数据帧 1.什么是数据帧 就是数据链路层的协议数据单元&#xff0c;它包括三部分&#xff1a;帧头&#xff0c;数据部分&#xff0c;帧尾…

路径规划(一) —— 环境描述(Grid Map Feature Map) 全局路径规划(最优路径规划(DijkstraA*star) 概率路径规划(PRMRRT))

路径规划问题就是把机器人的工作环境量化的描述出来&#xff0c;让机器人知道哪里可以走&#xff0c;哪里不可以走&#xff0c;从而规划出一条可行的轨迹&#xff0c;并且对于轨迹本身进行优化 环境的描述 对于环境的描述&#xff0c;我们一般使用两种方法——Grid map 和 Fe…

路径规划基本理论

路径规划有三个组成部分&#xff1a;空间表示、搜索和启发式算法&#xff0c; 空间表示 空间表示意思就是在执行路径规划之前&#xff0c;为目标构建地图环境。执行任何类型的路径规划&#xff0c;都需要先将地图环境离散化为图形。为了提高路径规划的效果&#xff0c;可以将地…

导航和路径规划

导航技术前言&#xff1a; 导航技术的移动机器人技术的核心和关键技术。自主移动机器人的导航就是让机器人可以自主按照内部预定的信息&#xff0c;或者依据传感器获取外部环境进行相应的引导&#xff0c;从而规划出一条适合机器人在环境中行走的路径。定位&#xff0c;就是机器…

基于采样的路径规划方法

与基于图搜索的方法相比&#xff0c;基于采样的路径规划算法不需要显式构建整个配置空间和边界。 0.概念 Complete Planner&#xff08;完备规划器&#xff09; Probabilistic Complete Planner&#xff08;概率完备的规划器&#xff09; Resolution Complete Planner&#xf…

路径规划算法:动态规划

如上图所示的实例中&#xff0c;寻找点A到点E代价最小的路径&#xff0c;这是典型的动态规划的应用场景&#xff0c;逆向寻优&#xff0c;正向求解一般分为3步&#xff0c;即三层循环&#xff1a; 第一层循环&#xff1a;遍历每一个阶段&#xff1b; 第二层循环&#xff1a;遍…

ROS 路径规划

目录 一、ROS路径规划算法【转】 二、机器人局部避障的动态窗口法(dynamic window approach) 三、自动驾驶路径规划DWA算法原理解析【转】 0、采样速度 1、oscillation cost function: 2、twirling cost function 3、obstacle function ​4、goal cost function 5. go…

路径规划算法概论

前言&#xff1a;真实世界中人类的路径规划是对记忆信息和实时感知信息综合分析的过程&#xff0c;在虚拟技术中属于行为控制层级的技术。 一&#xff0c;机器人路径规划分类&#xff1a; 1.全局路径规划&#xff08;环境完全已知&#xff09; 2.局部路径规划&#xff08;环境未…

自动驾驶路径规划概况

文章目录 前言介绍1. 路径规划在自动驾驶系统架构中的位置2. 全局路径规划的分类2.1 基础图搜索算法2.1.1 Dijkstra算法2.1.2 双向搜索算法2.1.3 Floyd算法 2.2 启发式算法2.2.1 A*算法2.2.2 D*算法 2.3 基于概率采样的算法2.3.1 概率路线图&#xff08;PRM&#xff09;2.3.2 快…

利用matlab来进行路径规划,matlab路径规划系列

前言:本博客将结合常用的路径规划算法进行matlab讲解。 一、路径规划问题所需操作 1.生成地图 告诉电脑你的当前地图环境。比如一个迷宫。这里面就涉及一些图像处理的内容,以及如何把地图转换为matlab数据 例子: 有一张原始地图: 现在要将这图片导入matlab中,转换为matlab…

AGV路径规划方法——A*算法

一、简单理解 它用来表示从当前方块到终点方块大概需要走多少步 b站视频链接 二、文献描述 1、基于时间窗的多AGV调度策略研究 冯鲁波. 基于时间窗的多AGV调度策略研究[D].四川大学,2021.DOI:10.27342/d.cnki.gscdu.2021.000278. 2.AGV自动运输系统调度及路径规划的研…

路径规划基本介绍(一)

一、路径规划的作用 路径规划主要是让目标对象在规定范围内的区域内找到一条从起点到终点的无碰撞安全路径。路径规划中有静态路径规划以及动态路径规划。这里仅针对静态路径规划方法进行简单的介绍&#xff0c;以下路径规划仅指在静态环境下的路径规划。 在进行路径规划的时候…

java 路径规划_应用内路径规划的简单实现

前言 华为Map Kit提供的路径规划API是一套以HTTPS形式提供的步行、骑行、驾车路径规划以及行驶距离计算接口&#xff0c;通过JSON格式返回路径查询数据&#xff0c;提供路径规划能力。 路径规划具体提供如下功能&#xff1a; 步行路径规划 API提供100km以内的步行路径规划能力。…

协同路径规划

目录 1. 背景介绍2. 现有的解决方案2.1. 遗传算法解决组合优化问题2.2. DARP STC 规划多车协同路径2.2.1. DARP: Divide Areas Algorithm for Optimal Multi-Robot Coverage Path Planning2.2.2. STC : Spanning Tree Coverage (STC) Algorithm 1. 背景介绍 区别与点对点的路…

arcgis发布路网路径规划服务

1、准备路网数据 导入文件地理数据库中(个人地理数据库会出问题) 2、开启编辑后打断相交处 我的数据带高度字段,所以是分高度打断 当然再用CG工具箱的工具更完美 2.1 如果需要路径返回高程才需要这一步

路径规划(path planning)

智能车辆有了行驶任务&#xff0c;智能车辆的路径规划就是在进行环境信息感知并确定车辆在环境中位置的基础上&#xff0c;按照一定的搜索算法&#xff0c;找出一条可通行的路径&#xff0c;进而实现智能车辆的自主导航。 路径规划的方法根据智能车辆工作环境信息的完整程度&a…

路径规划(RRT)

路径规划的核心内容是&#xff1a;在有碰撞的环境中&#xff0c;规划出一条从起始点到目标点的无碰撞路径。 路径规划算法特点总结&#xff1a; 完备性&#xff1a;起始点与目标点之间有路径解存在&#xff0c;那么一定可以找到解&#xff0c;若找不到解则说明一定没有解存在…

改进的 A*算法的路径规划(路径规划+代码+毕业设计)

更多视觉和自动驾驶项目请见&#xff1a; 小白学视觉 自动驾驶项目 引言 近年来&#xff0c;随着智能时代的到来&#xff0c;路径规划技术飞快发展&#xff0c;已经形成了一套较为成熟的理论体系。其经典规划算法包括 Dijkstra 算法、A算法、D算法、Field D算法等&#xff0c…

总结 | 六大路径规划算法

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 仅作学术分享&#xff0c;不代表本公众号立场&#xff0c;侵权联系删除 转载于&#xff1a;https://zhuanlan.zhihu.com/p/51372134&#xff0c; 知乎ID:搬砖的旺财 1.自…