当前位置: 首页 > news >正文

使用 Netty 自定义解码器处理粘包和拆包问题详解

使用 Netty 自定义解码器处理粘包和拆包问题详解

在网络编程中,粘包和拆包问题是常见的挑战。粘包是指多个数据包在传输过程中粘在一起,而拆包是指一个数据包在传输过程中被拆分成多个部分。Netty 是一个高性能、事件驱动的网络应用框架,提供了强大的工具来解决这些问题。

本文将详细介绍如何使用 Netty 创建自定义解码器和编码器来处理粘包和拆包问题。通过实现一个基于固定长度的解码器和编码器,我们可以确保数据包在传输过程中被正确解析和处理。本文将涵盖以下内容:

粘包与拆包问题

  • 粘包:指的是多个数据包粘在一起,接收端一次性接收多个数据包的情况。

  • 拆包:指的是一个数据包被拆分成多个部分,接收端多次接收到部分数据包的情况。

实现步骤

1. 创建 Netty 项目

首先,创建一个 Maven 项目,并添加 Netty 依赖:

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.68.Final</version>
</dependency>

2. 自定义解码器

我们需要实现一个自定义解码器来处理粘包和拆包问题。这里使用的是基于固定长度的解码器。

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;import java.util.List;public class CustomDecoder extends ByteToMessageDecoder {private static final int HEADER_SIZE = 4; // 包头的长度,假设包头是一个int表示整个包的长度@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {while (in.readableBytes() >= HEADER_SIZE) {in.markReaderIndex(); // 标记当前读指针位置int dataLength = in.readInt(); // 读取包头,获取数据包长度if (in.readableBytes() < dataLength) {in.resetReaderIndex(); // 重置读指针到标记位置return; // 等待更多的数据到达}byte[] data = new byte[dataLength];in.readBytes(data);out.add(data); // 将解码后的数据添加到输出列表中}}
}

3. 自定义编码器

为了与解码器配合,我们还需要自定义编码器。

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;public class CustomEncoder extends MessageToByteEncoder<byte[]> {@Overrideprotected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception {out.writeInt(msg.length); // 写入包头,数据包长度out.writeBytes(msg); // 写入实际数据}
}

4. 配置 Netty 服务端

配置 Netty 服务端,使用自定义解码器和编码器。

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {private final int port;public NettyServer(int port) {this.port = port;}public void start() throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup(); // 接受进来的连接EventLoopGroup workerGroup = new NioEventLoopGroup(); // 处理已经被接受的连接try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 使用 NIO 传输.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 配置解码器和编码器ch.pipeline().addLast(new CustomDecoder());ch.pipeline().addLast(new CustomEncoder());// 配置业务逻辑处理器ch.pipeline().addLast(new ServerHandler());}}).option(ChannelOption.SO_BACKLOG, 128) // 配置 TCP 参数.childOption(ChannelOption.SO_KEEPALIVE, true); // 保持连接// 绑定端口,开始接受进来的连接ChannelFuture f = b.bind(port).sync();// 等待服务器 socket 关闭f.channel().closeFuture().sync();} finally {// 关闭 EventLoopGroup,释放所有资源workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {new NettyServer(8080).start();}
}

5. 配置 Netty 客户端

配置 Netty 客户端,同样使用自定义解码器和编码器。

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class NettyClient {private final String host;private final int port;public NettyClient(String host, int port) {this.host = host;this.port = port;}public void start() throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class) // 使用 NIO 传输.option(ChannelOption.SO_KEEPALIVE, true) // 保持连接.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 配置解码器和编码器ch.pipeline().addLast(new CustomDecoder());ch.pipeline().addLast(new CustomEncoder());// 配置业务逻辑处理器ch.pipeline().addLast(new ClientHandler());}});// 连接服务器ChannelFuture f = b.connect(host, port).sync();// 等待连接关闭f.channel().closeFuture().sync();} finally {// 关闭 EventLoopGroup,释放所有资源group.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {new NettyClient("localhost", 8080).start();}
}

6. 实现服务端和客户端处理器

服务端和客户端处理器分别处理接收到的数据。

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;public class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {byte[] data = (byte[]) msg;System.out.println("Server received: " + new String(data));// 处理数据逻辑,可以根据业务需求进行数据处理}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close(); // 关闭连接}
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;public class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {byte[] data = "Hello, Netty!".getBytes();ctx.writeAndFlush(data); // 发送数据}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {byte[] data = (byte[]) msg;System.out.println("Client received: " + new String(data));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close(); // 关闭连接}
}

总结

通过自定义解码器和编码器,Netty 可以有效处理粘包和拆包问题。本文介绍了如何实现一个基于固定长度的数据包解码器和编码器,并展示了在 Netty 客户端和服务端中使用自定义解码器和编码器的完整代码示例。通过这种方式,可以确保数据包在传输过程中被正确解析和处理。

相关文章:

使用 Netty 自定义解码器处理粘包和拆包问题详解

使用 Netty 自定义解码器处理粘包和拆包问题详解 在网络编程中&#xff0c;粘包和拆包问题是常见的挑战。粘包是指多个数据包在传输过程中粘在一起&#xff0c;而拆包是指一个数据包在传输过程中被拆分成多个部分。Netty 是一个高性能、事件驱动的网络应用框架&#xff0c;提供…...

SDK编译IO Domain电压选择

开源鸿蒙硬件方案领跑者 触觉智能 本文适用于在Purple Pi OH开发板进行分区镜像烧录。触觉智能的Purple Pi OH鸿蒙开源主板&#xff0c;是华为Laval官方社区主荐的一款鸿蒙开发主板。 该主板主要针对学生党&#xff0c;极客&#xff0c;工程师&#xff0c;极大降低了开源鸿蒙…...

如何在纯内网环境下,将EasyCVR视频汇聚网关通过4G与第三方公网云平台级联?

EasyCVR视频汇聚网关是TSINGSEE青犀软硬一体的一款产品&#xff0c;可提供多协议的接入、音视频采集、处理&#xff0c;能实现海量前端设备的轻量化接入/转码/分发、视频直播、云端录像、云存储、检索回看、智能告警、平台级联等&#xff0c;兼容多种操作系统&#xff0c;轻松扩…...

2024-06-14 AI资讯:CCF论坛探讨大模型挑战,启动安全赛

智源社区 共话大模型技术进展与挑战&#xff0c;CCF大模型论坛北京会议圆满落幕&#xff01; 2024 年 6 月 6 日中国计算机学会大模型论坛&#xff08;CCF FoLM&#xff09;主题会议在北京顺利举办。本次会议主题为“大模型技术进展与挑战”&#xff0c;各位专家围绕大模型技…...

玩转Matlab-Simscape(初级)- 10 - 基于COMSOLSimulink 凸轮机构的控制仿真

** 玩转Matlab-Simscape&#xff08;初级&#xff09;- 10 - 基于COMSOL&Simulink 凸轮机构的控制仿真 ** 目录 玩转Matlab-Simscape&#xff08;初级&#xff09;- 10 - 基于COMSOL&Simulink 凸轮机构的控制仿真 前言一、简介二、在Solidworks中创建3D模型&#xff…...

spark学习总结

系列文章目录 第1天总结&#xff1a;spark基础学习 1- Spark基本介绍&#xff08;了解&#xff09;2- Spark入门案例&#xff08;掌握&#xff09;3- 常见面试题&#xff08;掌握&#xff09; 文章目录 系列文章目录前言一、Spark基本介绍1、Spark是什么1.1 定义1.2 Spark与M…...

eNSP学习——帧中继基本配置

目录 主要命令 基本原理 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、静态与动态映射的配置 3、子接口配置和静态路由 主要命令 [R1]int s1/0/0 [R1-Serial1/0/0]link-protocol fr //配置链路层协议为FR Warning: The encapsulation protocol…...

XML Encoding = ‘GBK‘ after STRANS,中文乱码

最近帮同事处理了一个中信银行银企直连接口的一个问题&#xff0c;同事反馈&#xff0c;使用STRANS转换XML后&#xff0c;encoding始终是’utf-16’,就算指定了GBK也不行。尝试了很多办法始终不行&#xff0c;发到银行的数据中&#xff0c;中文始终是乱码。 Debug使用HTML视图…...

C 语言通用MySQL 功能增删查改功能.

前提条件&#xff1a;Ubuntu 22.04.4 LTS、MSQL 8数据库 并且已经安装MySQL 8 开发库。如果没有安装&#xff0c;可以查考&#xff1a;C 语言连接MySQL数据库 项目要求: 1、完成MySQL数据库增删改查通用功能封装 2、编辑makefile 文件实现项目动态更新和快速编译 项目结构…...

Java学习 - MySQL表 增减删查

建表 按照DDL练习&#xff0c;先创建student表和home表 插入【增】 向student表中同时插入三个新的字段【1,Alice,f,15353535353】【2,Bob,m,13646464646】【3,Jack,m,13745908686】 INSERT INTO student(id,name,gender,phone) VALUES(1,Alice,f,15353535353),(2,Bob,m,1364…...

力扣SQL50 有趣的电影 简单查询

Problem: 620. 有趣的电影 Code select * from cinema where id % 2 1 and description ! boring order by rating desc;...

01. Java并发编程简介

1. 前言 大家好&#xff0c;本节我们来一起学习 Java 并发编程的核心原理。 作为本专题的第一个小节&#xff0c;我们先来了解下什么是并发编程&#xff0c;以及学习并发编程的必要性&#xff0c;及学习过程应该注意的事项。 下面&#xff0c;我们先了解一下 Java 并发编程。…...

使用Node.js+Express开发简单接口

Node.js 和 Express 是非常流行的组合&#xff0c;用于开发快速、高效的 web 服务器和 API。下面是一个基础教程&#xff0c;介绍如何使用 Node.js 和 Express 开发一个简单的 API。 1. 安装 Node.js 和 npm 首先&#xff0c;确保您已经安装了 Node.js 和 npm&#xff08;Nod…...

【Python】使用OpenCV特征匹配检测图像中的【特定水印】

如果没有方向 往哪里走都是前方 做自己的光 不需要多亮 曾受过的伤 会长出翅膀 大雨冲刷过的天空会更加明亮 流过泪的眼睛也一样 做自己的光 悄悄的发亮 逆风的方向 更容易飞翔 世界怎样在于你凝视它的目光 那未曾谋面过的远方 或许就在身旁 &#x1f3b5…...

基于 Clang和LLVM 的 C++ 代码静态分析工具开发教程

基于 Clang和LLVM 的 C 代码静态分析工具开发教程 简介 静态代码分析是一种在不实际运行程序的情况下对源代码进行分析的技术。它可以帮助开发者在编译之前发现潜在的错误、安全漏洞、性能问题等。 在 C 开发中&#xff0c;有几种常用的静态代码分析工具&#xff0c;它们可以…...

Mathtype与word字号对照+Mathtype与word字号对照

字体大小对照表如下 初号44pt 小初36pt 一号26pt 小一24pt 二号22pt 小二18pt 三号16pt 小三15pt 四号14pt 小四12pt 五号10.5pt 小五9pt 六号7.5pt 小六6.5pt 七号5.5pt 八号5pt 1 保存12pt文件 首选选择第一个公式&#xff0c;将其大小改为12pt 然后依次选择 “预置”—…...

PHP 8.4有哪些新功能值得关注

属性钩子&#xff08;Property Hooks&#xff09; 允许开发者为每个属性定义自己的get和set钩子&#xff0c;以在属性访问前后添加自定义逻辑。属性钩子通过__get()和__set()方法实现&#xff0c;类似于其他编程语言&#xff08;如Kotlin、C#和Swift&#xff09;中的属性访问器…...

PyCharm新手入门

前言 在之前《Python集成开发工具的选择》一文中介绍了python初学者可以使用Jupyter Notebook&#xff0c;Jupyter Notebook简单易用&#xff0c;可以用来练习代码编写&#xff0c;但是实际生产开发环境使用这个工具是远远不够用的&#xff0c;因为实际软件开发中需要软件调试…...

[Linux] 系统管理

全局配置文件 用户个性化配置 配置文件的种类 alias命令和unalias命令 进程管理 进程表...

Xcode无法使用设备:Failed to prepare the device for development

问题&#xff1a; Xcode无法使用设备开发&#xff0c;失败报错如下&#xff1a; Failed to prepare the device for development. This operation can fail if the version of the OS on the device is incompatible with the installed version of Xcode. You may also need…...

AWS无服务器 应用程序开发—第十二章 AWS Step Functions

AWS Step Functions 是一种服务,用于协调和管理分布式应用程序中的多个 AWS 服务和 Lambda 函数。它通过创建有状态的工作流来简化和自动化应用程序的各种工作流程,使得复杂的业务逻辑可以以可管理和可调试的方式实现。 主要功能和特点: 状态机定义: 使用 JSON 或 Amazo…...

Linux tcpdump详解

目录 前言&#xff1a;BPF伯克利包过滤器介绍1.BPF语法&#xff08;tcpdump语法&#xff09;2.逻辑运算符3.常用的原子条件1. 协议相关的原子条件2. 地址相关的原子条件3. 端口相关的原子条件4. 网络层和链路层(mac地址&#xff09;原子条件5. 广播和多播6. VLAN 相关的原子条件…...

vue2实现打印功能(vue-print-nb的实现)

实现效果&#xff1a; 引入插件 npm install vue-print-nb --save import Print from vue-print-nb Vue.use(Print) <div ref"printTest" id"printTest"><div style"text-align: center; page-break-after: always"><div style…...

某全国增值税发票查验平台 接口JS逆向

注意&#xff0c;本文只提供学习的思路&#xff0c;严禁违反法律以及破坏信息系统等行为&#xff0c;本文只提供思路 本文的验证码网址如下&#xff0c;使用base64解码获得 aHR0cHM6Ly9pbnYtdmVyaS5jaGluYXRheC5nb3YuY24v 这个平台功能没什么好说的&#xff0c;就是发票查验&am…...

前端练习小项目——视觉冲击卡片

前言&#xff1a; 前言&#xff1a;在学习完HTML和CSS之后&#xff0c;我们就可以开始做一些小项目了&#xff0c;本篇文章所讲的小项目为——视觉冲击卡片 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 先让我们看一下效果&a…...

从0到1:手动测试迈向自动化——手机web应用的自动化测试工具

引言&#xff1a; 在当今移动互联网时代&#xff0c;手机web应用已经成为人们生活中不可或缺的一部分。为了保证手机web应用的质量和稳定性&#xff0c;自动化测试工具变得十分重要。本文将介绍手机web应用自动化测试工具的选择和使用&#xff0c;提供一份超详细且规范的指南&a…...

磁盘未格式化:深度解析、恢复策略与预防措施

一、磁盘未格式化的定义与现象 在计算机存储领域&#xff0c;磁盘未格式化通常指的是磁盘分区或整个磁盘的文件系统信息出现丢失或损坏的情况&#xff0c;导致操作系统无法正确读取和识别磁盘上的数据。当尝试访问这样的磁盘时&#xff0c;系统往往会弹出一个警告框&#xff0…...

Qwen2在Java项目中如何实现优雅的Function_Call工具调用

在当今AI技术飞速发展的背景下&#xff0c;大语言模型如Qwen2和GLM-4凭借其强大的语言处理能力&#xff0c;在诸多领域展现出了巨大的潜力。然而&#xff0c;大模型并非全知全能&#xff0c;它们在处理特定任务时&#xff0c;尤其是在需要与外部系统交互或执行具体功能时&#…...

【SPIE独立出版 | 往届均已完成EI检索】2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024)

2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024) 2024 International conference on Cloud Computing, Performance Computing and Deep Learning *CCPCDL往届均已完成EI检索&#xff0c;最快会后4个半月完成&#xff01; 一、重要信息 大会官网&#xff1a;www…...

MYSQL 四、mysql进阶 4(索引的数据结构)

一、为什么使用索引 以及 索引的优缺点 1.为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录中找到对应文章的页码&#xff0c;便可快速定位到需要的文章。Mysql中也是一样的道理&#xff0c;进行数…...

网站建设最好的/百度关键词热搜

安装Python IDE&#xff1a; Eclipse 支持好多插件&#xff0c;如何设计安装一个插件&#xff0c; 如下图&#xff1a; 1. 从菜单里面 Help->Install new software. 2. 指定plugin 所在的url。 3. 输入关键字&#xff0c;比如 pydev 4. 从匹配的plugin 里面选择。 python工…...

免费空间 个人网站 google广告联盟/百度快速排名软件原理

第一天&#xff1a;组织会议 第二天&#xff1a;发表博客 第三天&#xff1a;组织会议 第四天&#xff1a;发表博客 第五天&#xff1a;搜集要用到的图片&#xff0c;组织会议 第六天&#xff1a;发表博客 第七天&#xff1a;组织会议 第八天&#xff1a;发表博客 第九天&#…...

网站中数据查询如何做/媒体135网站

一、基本设置 1、Tools \ Options&#xff0c;各种基本设置 1.1 Tools \ Options \ HFSS Options-> Duplicate boundaries/mesh operations with geometry , 被复制的集合图形&#xff0c;默认拥有同样的边界特性 1.2 Tools \ Options \ Modeler Options-> (operations)A…...

lnmp wordpress tp/小程序推广赚佣金平台

NetScaler101&#xff1a;会话保持 转载于:https://blog.51cto.com/netscaler/1879452...

网站建立供应商/百度竞价教程

下面是一些关于大数据挖掘的知识点&#xff0c;今天和大家一起来学习一下。1. 数据、信息和知识是广义数据表现的不同形式。 2. 主要知识模式类型有&#xff1a;广义知识&#xff0c;关联知识&#xff0c;类知识&#xff0c;预测型知识&#xff0c;特异型知识3. web挖掘研究的主…...

湖南智能网站建设多少钱/百度指数人群画像哪里查询

经常有学员问我&#xff0c;学习上位机要不要买PLC硬件&#xff1f;我一般的回答是&#xff1a;富则自行购买&#xff0c;穷则搭建仿真。PLC硬件&#xff0c;对于学习上位机来说&#xff0c;是锦上添花的事&#xff0c;经济条件允许&#xff0c;有则更好&#xff0c;条件不允许…...