从零开始学netty——如何面对粘包和拆包

news/2024/7/15 16:54:00 标签: netty, 网络

为什么80%的码农都做不了架构师?>>>   hot3.png

本篇只有部分代码,重复代码见
从零开始学netty——第一个netty程序
从零开始学netty——认识decoder

粘包和拆包

tcp是流式套接字,这个就是造成了收到的内容和传输的的断句是不同的。这个可以类比古代没有标点,断句就可能有多种的变化。例如“没有鸡鸭也可以"这句。你可能收到是的没有鸡鸭也可以,也可能收到的是没有鸡,然后又收到鸭也可以。粘包说的是两次发送的一次收到了,拆包则是一次发送的,分两次收到。

产生的原因

原因大概说一下,详细了解的话,去专门看看tcp协议。

  1. write写入的字节大于套接字发送缓冲区的大小。
  2. 进行mss大小的tcp分段。
  3. 以太网帧的payload大于mtu进行ip分片。

解决方法

  1. 固定长度,例如每次只发200个字节,也只读200个字节,度不够就等待
  2. 使用分隔符,例如回车换行
  3. 用消息头和消息体

不知不觉使用的处理方式

其实很多人说自己压根没有专门做过粘包和拆包的处理,程序也没问题。我们仔细回想一下,如果自己写个socket的demo的时候,是不是还用的是包装流的做法,例如使用了BufferedReader,并且使用了readLine方法,每次取一行。这里就是上面所说的使用了分隔符的解决方法。

解决方式的对比

  1. 固定长度的方法麻烦的是长度固定,不够要补充空,浪费资源,而且不够的话,还得修改长度,扩展不好。
  2. 分隔符的方式比较简单,就是怕输入的内容也有分割符。
  3. 自定义消息这种是比较常用的,麻烦的是需要自己定义消息规则,在处理简单的情况的时候,上面两种完全可以够用。

demo演示

	    ch.pipeline().addLast(new LineBasedFrameDecoder(2000));

LineBasedFrameDecoder就是类比我们BufferedReader的readLine的功能。加上这个解码器,你就发现telnet send发出收不到消息了,需要发送一个回车换行符号才可以。

							ch.pipeline().addLast(
									new DelimiterBasedFrameDecoder(10000, Unpooled.copiedBuffer("$".getBytes())));

DelimiterBasedFrameDecoder是自定义分隔符的。这里我们使用$来作为分隔符。使用telnet发送hhh$,就会收到hhh

            ch.pipeline().addLast(new FixedLengthFrameDecoder(2));

FixedLengthFrameDecoder是定长的解码器,这里设置2的长度,你使用telnet发送bbbbbb,会分开接收为3个bb。

用消息头和消息体的情况和编码器和解码器的的小结一起写。

小结

netty提供了很常用的几种处理粘包和拆包的方式。在简单的逻辑下,他们是可以满足要求的,可以不用重复造轮子。

转载于:https://my.oschina.net/xpbob/blog/1810129


http://www.niftyadmin.cn/n/1792040.html

相关文章

oracle rac转mysql_从Oracle转到Mysql前需了解的50件事

我本人比较关心的几点:1. 对子查询的优化表现不佳.2. 对复杂查询的处理较弱4. 性能优化工具与度量信息不足12. 支持 SMP (对称多处理器),但是如果每个处理器超过 4 或 8 个核(core)时,Mysql 的扩展性表现较差.15. 没有基于回滚(roll-back)的恢复功能,只有…

PCA revisit

都知道PCA可以做降维,那它为什么可以降维,究竟是怎么降维的呢? 1. 为什么我们要降维? 我们的样本数据好好的,为什么要去做降维,第一个要想清楚这个问题。 也许你是要训练一个分类器,觉得当前特征…

SpringCloud实战2-Ribbon客户端负载均衡

前面我们已经完成了注册中心和服务提供者两个基础组件。接着介绍使用Spring Cloud Ribbon在客户端负载均衡的调用服务。 ribbon 是一个客户端负载均衡器,可以简单的理解成类似于 nginx的负载均衡模块的功能。 主流的LB方案可分成两类: 一种是集中式LB, 即…

mysql创建部门信息表_day02_mysql:数据表创建

基于不同的操作目的,为提高效率,创建数据库时可使用不同的数据库存储引擎,最常见时事务型InnoDBmysql 常见数据类型字符串: char 固定长度, varchar(n) 可变长度数值: int , float(m, d) &#…

小程序之图片瀑布流(最全实现方式,额外加送懒加载)

效果图 来来来,看啊看,外面的世界多好看, 效果图展示的是瀑布流布局 && 懒加载的效果 数据 图片数据来源张鑫旭的网络日志 先说下我们的图片链接格式 所有的链接都是http://cued.xunlei.com/demos/publ/img/P_${name}.jpg这样的格式&…

mysql左连接查询举例_mysql左右连接查询(有示例图)

小小的连接查询,其实里面有很多学问,今天我就来简单剖析一下。左连接,右连接,内连接的本质:将两个表的数据依据一定条件横向连接起来。给出建表语句:--------------------------------------------------cr…

安装Maven、Eclipse设置、添加地址JAR

1.下载Maven 地址:http://maven.apache.org/download.cgi 2.安装Maven 系统变量:MAVEN_HOME D:\maven\apache-maven-3.3.9 系统变量:path %MAVEN_HOME%\bin 相信大家都有配过环境变量的,详细步骤就不说了,对着把属性…

剑指Offer_28_数组中出现次数超过一半的数字

题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 解题思路 解法1 超过一半的数据一…