Netty通信中的粘包半包问题(三)

之前我们介绍了用特殊分隔符来分割每个报文,但是如果传输的数据中恰好有个特殊分隔符,它将会被拆分成多个,于是,为了进一步避免这个问题,还有一种解决方案是在两端的channelPipeline中用一个固定长度来区分,这样也可以解决粘包半包的问题

1.Server

package splicing.fixed;import constant.Constant;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;import java.net.InetSocketAddress;public class FixedLengthEchoServer {public static final String RESPONSE = "Welcome to Netty";public static void main(String[] args) throws InterruptedException {FixedLengthEchoServer fixedLengthEchoServer = new FixedLengthEchoServer();System.out.println("服务器即将启动");fixedLengthEchoServer.start();}public void start() throws InterruptedException {FixedLengthServerHandler serverHandler = new FixedLengthServerHandler();EventLoopGroup group = new NioEventLoopGroup();// 线程组try {// 服务端启动必须ServerBootstrap b = new ServerBootstrap();b.group(group)// 将线程组传入.channel(NioServerSocketChannel.class) // 指定使用NIO进行网络传输.localAddress(new InetSocketAddress(Constant.DEFAULT_PORT)) // 指定服务器监听端口// 服务端每接收到一个连接请求,就会新启一个Socket通信,也就是channel// 所以下面这段代码的作用就是为这个子channel增加handler.childHandler(new ChannelInitializerImp());// 异步绑定到服务器,sync()会阻塞直到完成ChannelFuture f = b.bind().sync();System.out.println("服务器启动完成,等待客户端的连接和数据.....");// 阻塞直到服务器的channel关闭f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}private static class ChannelInitializerImp extends ChannelInitializer<Channel> {@Overrideprotected void initChannel(Channel ch) throws Exception {ch.pipeline().addLast(new FixedLengthFrameDecoder(FixedLengthEchoClient.REQUEST.length()));ch.pipeline().addLast(new FixedLengthServerHandler());}}
}
package splicing.fixed;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;import java.util.concurrent.atomic.AtomicInteger;public class FixedLengthServerHandler extends ChannelInboundHandlerAdapter {private AtomicInteger counter = new AtomicInteger(0);@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf in = (ByteBuf) msg;String request = in.toString(CharsetUtil.UTF_8);System.out.println("Server Accept[" + request +" ] and the counter is :" + counter.incrementAndGet());ctx.writeAndFlush(Unpooled.copiedBuffer(FixedLengthEchoServer.RESPONSE.getBytes()));
//        super.channelRead(ctx, msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();
//        super.exceptionCaught(ctx, cause);}
}

2.Client

package splicing.fixed;import constant.Constant;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;import java.net.InetSocketAddress;public class FixedLengthEchoClient {public static final String REQUEST = "Mark,zhuge,zhouyu,fox,loulan";private final String host;public FixedLengthEchoClient(String host) {this.host = host;}public void start() throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {// 客户端启动必须Bootstrap b = new Bootstrap();b.group(group)// 将线程组传入.channel(NioSocketChannel.class) // 指定使用NIO进行网络传输.remoteAddress(new InetSocketAddress(host, Constant.DEFAULT_PORT)).handler(new ChannelInitializerImp());ChannelFuture f = b.connect().sync();System.out.println("已连接到服务器....");f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}private static class ChannelInitializerImp extends ChannelInitializer<Channel> {@Overrideprotected void initChannel(Channel ch) throws Exception {ch.pipeline().addLast(new FixedLengthFrameDecoder(FixedLengthEchoServer.RESPONSE.length()));ch.pipeline().addLast(new FixedLengthClientHandler());}}public static void main(String[] args) throws InterruptedException {new FixedLengthEchoClient(Constant.DEFAULT_SERVER_IP).start();}
}
package splicing.fixed;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;import java.util.concurrent.atomic.AtomicInteger;public class FixedLengthClientHandler extends SimpleChannelInboundHandler<ByteBuf> {private AtomicInteger counter = new AtomicInteger(0);@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {System.out.println("client Accept [" + msg.toString(CharsetUtil.UTF_8)+ "] and the counter is :" + counter.incrementAndGet());}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf msg = null;for (int i = 0; i < 100; i++) {msg = Unpooled.buffer(FixedLengthEchoClient.REQUEST.length());msg.writeBytes(FixedLengthEchoClient.REQUEST.getBytes());ctx.writeAndFlush(msg);}
//        super.channelActive(ctx);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();
//        super.exceptionCaught(ctx, cause);}
}

3.结果展示

在这里插入图片描述
在这里插入图片描述

这种方案的限制在于要提前直到客户端和服务端要发送的报文,并且这个长度是固定的,不能变,如果变了,还是会产生粘包半包的问题,那么有的人可能会想,有没有更好的解决方案,别着急,下一期我们接着分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/630062.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8s(一)Pod资源——Pod介绍、创建Pod、Pod简单资源配额

目录 Pod概述 pod网络 pod存储 pod和容器对比 创建pod的方式 pod运行方式分类 Pod的创建 Pod的创建过程 通过kubectl run来创建pod 通过yaml文件创建&#xff0c;yaml文件简单写法 Pod简单操作 Pod的标签labels Pod的资源配额resource 测试 Pod概述 Kubernetes …

贪心算法-活动安排-最详细注释解析

贪心算法-活动安排-最详细注释解析 题目&#xff1a; 学校在最近几天有n个活动&#xff0c;这些活动都需要使用学校的大礼堂&#xff0c;在同一时间&#xff0c;礼堂只能被一个活动使用。由于有些活动时间上有冲突&#xff0c;学校办公室人员只好让一些活动放弃使用礼堂而使用…

Arm Generic Interrupt Controller v3 and v4(GICv3v4)学习(一)

提示 该博客主要为个人学习&#xff0c;通过阅读官网手册整理而来&#xff08;个人觉得阅读官网的英文文档非常有助于理解各个IP特性&#xff09;。若有不对之处请参考参考文档&#xff0c;以官网参考文档为准。 Arm Generic Interrupt Controller v3 and v4学习一共分为三章&…

Revealing the Dark Secrets of MIM

论文名称&#xff1a; Revealing the Dark Secrets of Masked Image Modeling 发表时间&#xff1a;CVPR2022 作者及组织&#xff1a;Zhenda Xie, Zigang Geng, Hu Han等&#xff0c;来自清华&#xff0c;中科院&#xff0c;微软亚洲研究院。 前言 本文尝试探讨MIM为何有效的原…

JavaScript 学习笔记(Day5)

「写在前面」 本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. JavaScript 学习笔记&#xff08;Day1&#xff09; 2. JavaSc…

数据结构奇妙旅程之二叉树初阶

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

IDEA无法解析jdk自带的类的解决办法

1.问题 IDEA在有些时候&#xff0c;会出现这个错误&#xff0c;就是jdk自带的java类找不到而报错。 例如下面的就是Object找不到&#xff0c;我们知道jdk自带的类是不用import包的&#xff0c;这里报错了&#xff0c;IDEA会提示你去导入类&#xff0c;其实这个提示也不是真正…

Ubuntu 22.04 基础环境搭建

这是Ubuntu软件安装系列的第一篇&#xff0c;我们来聊聊基础环境搭建。 这个专栏主要讲一些常见服务端软件的安装和配置&#xff0c;当然也包括对软件架构和作用的分析&#xff0c;以及使用的场景的介绍。 注意我们这里使用的Ubuntu的版本是22.04&#xff0c;基本上大厂的云服…

Go语言热重载和优雅地关闭程序

Go语言热重载和优雅地关闭程序 我们有时会因不同的目的去关闭服务&#xff0c;一种关闭服务是终止操作系统&#xff0c;一种关闭服务是用来更新配置。 我们希望优雅地关闭服务和通过热重载重新加载配置&#xff0c;而这两种方式可以通过信号包来完成。 1、代码实现 package…

产品经理与产品运营的区别和联系

一、两者的职责区别 产品经理的目的&#xff1a;是创造有价值的产品 产品运营的目的&#xff1a;是让产品能有效的发挥出它应有的价值 二、两者的工作内容区别产品经理的工作内容 产品的经理的目的是创造有价值的产品&#xff0c;因此产品经理的所有工作都是围绕着&#xf…

CentOS安装maxwell

CentOs安装maxwell 一、简介二、准备工作三、安装1、下载安装包2、解压3、编写配置文件4、启动maxwell5、验证6、停止maxwell 四、说明1、更新数据2、插入数据3、删除数据 五、遇到问题 一、简介 maxwell是由美国Zendesk公司开源&#xff0c;它通过读取mysql的binlog日志&#…

vscode mysql cmake windows 常见问题和推荐文章

1.在windows中安装mingw64和cmake&#xff08;可查一下网上的安装教程&#xff09;&#xff0c;配置环境变量 2.在vscode中用CMake构建项目的时候&#xff0c;可能会出现这样的问题:“The C compiler identification is unknownn...”,可参考这篇博客 在windows下使用Vscode用…

面试题之ElasticSearch

面试题之ElasticSearch 1.es的基础知识2. es的集群、节点、分片、副本分片的定义&#xff1f;3. es为什么快&#xff1f;4. 倒排索引的原理是什么&#xff1f;5. es的segment是什么&#xff1f;6. es的分段存储和分段索引的概念及区别&#xff1f;7. 索引相关的问题&#xff1f…

uni-app基础详解(组件、弹窗、数据缓存、页面跳转)

uni-app基础详解&#xff08;组件、弹窗、数据缓存、页面跳转&#xff09; uni-app组件scroll-viewswipertext 文本button 按钮input 输入框radio 单选checkbox 多选picker 选择器slider 滑块textarea 文本域 弹窗提示框 uni.showLoading提示弹窗 uni.showToast确定取消框 uni.…

Flutter系列:Flutter常见问答(可用于面试)

Flutter系列 Flutter常见问答 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/135604801 【简介】&#…

服务器感染了.DevicData-P-XXXXXXXX勒索病毒,如何确保数据文件完整恢复?

引言&#xff1a; 在当今数字化时代&#xff0c;勒索病毒已成为网络安全威胁的一个严峻问题。其中&#xff0c;.DevicData-P-XXXXXXXX 勒索病毒以其恶意加密文件的手段引起了广泛关注。本文将介绍该病毒的特点、数据恢复方法以及如何预防遭受其攻击。 如不幸感染这个勒索病毒&…

【Java数据结构】03-二叉树,树和森林

4 二叉树、树和森林 重点章节&#xff0c;在选择&#xff0c;填空&#xff0c;综合中都有考察到。 4.1 掌握二叉树、树和森林的定义以及它们之间的异同点 1. 二叉树&#xff08;Binary Tree&#xff09; 定义&#xff1a; 二叉树是一种特殊的树结构&#xff0c;其中每个节点…

入门clickhouse的坑

常规的关系数据库已经不能满足现有业务需求&#xff0c;于是&#xff0c;装了一个ck玩玩&#xff0c;结果&#xff0c;妥妥的跳坑&#xff01; 安装&#xff0c;首页就是一行语句&#xff0c;curl就可以安装了&#xff0c;确实很简单。 写了一个小工具&#xff0c;把整个sqls…

Python(wordcloud):根据词频信息(xlsx、csv文件)绘制词云图

一、前言 本文将介绍如何用python根据词频信息&#xff08;xlsx、csv文件&#xff09;绘制词云图&#xff0c;除了绘制常规形状的词云图&#xff08;比如长方形&#xff09;&#xff0c;还可以指定词云图的形状。 二、安装并引入相关的库 1、安装相关的库 pip install jieb…

Oracle/DM序列基本使用

序列(SEQUENCE)是序列号生成器&#xff0c;可以为表中的行自动生成序列号&#xff0c;产生一组等间隔的数值(类型为数字)。其主要的用途是生成表的主键值&#xff0c;可以在插入语句中引用&#xff0c;也可以通过查询检查当前值&#xff0c;或使序列增至下一个值。序列是一个计…