Netty框架之TCP粘包/半包解决方案

  • 一.TCP粘包
  • 二.TCP半包
  • 三.TCP粘包/半包解决方案
    • 1.FixedLengthFrameDecoder定长解析器
    • 2.LineBasedFrameDecoder行解析器
    • 3.LengthFieldBasedFrameDecoder

谈到TCP粘包/半包的解决方案,我们不妨先认识造成TCP粘包/半包的原因有哪些,以便于更深刻理解解决方案的原理

一.TCP粘包

1.现象:发送:abc,def,接收:abcdef
2.原因:

  • 应用层:接受数据的Bytebuf缓冲区设置太大(Netty默认为1024)存储了多个TCP包,一次性取的时候取出缓冲区所有数据,导致多个包粘在一起.
  • 滑动窗口:发送方发送消息太快,接收方接收消息也快,但是处理消息太慢,并且接收窗口足够大,那么此时消息就会堆积在接收窗口,那么就会导致多个包粘在一起
  • Nagle算法:Nagle算法是操作系统底层自动实现的,为了减少发送次数,提高效率,操作系统会在缓冲区未满的时候等待消息填充,直到缓冲区满的时候一并发送,造成粘包

二.TCP半包

1.现象:发送:abcdef,接收:abc,def
2.原因:

  • 应用层:接受数据的Bytebuf缓冲区设置太小(Netty默认为1024)存储不了一个完整的TCP包,一次性只能取出TCP包的部分数据
  • 滑动窗口:发送方发送窗口较大,接收方接收窗口较小,导致接收方只能接收TCP包的部分数据,导致TCP半包
  • MSS限制:为了限制TCP包的大小,会将大的TCP包分组成多个小的TCP包发送,导致半包问题

三.TCP粘包/半包解决方案

1.FixedLengthFrameDecoder定长解析器

向pipeline中加入FixedLengthFrameDecoder(int length)定长解析器,取出指定字节长度的数据作为完成数据,不过这要求完整数据的长度是定长

使用方法,请尝试理解下面源码

public class FixedLengthFrameDecoderTest {public static ByteBuf Message(){StringBuilder sb = new StringBuilder();char c = 'a';for(int i=0;i<20;i++){sb.append(c);c++;}return Unpooled.copiedBuffer(sb.toString(),StandardCharsets.UTF_8);}public static void main(String[] args) {EmbeddedChannel channel = new EmbeddedChannel(//定长解析器,取出指定字节长度的数据new FixedLengthFrameDecoder(10),new SimpleChannelInboundHandler<ByteBuf>() {@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {//将Bytebuf的信息读取到字节数组int len = buf.readableBytes();byte[] msg = new byte[len];buf.readBytes(msg);//把字节数组转化为String输出System.out.println(new String(msg,0,len));}});//模拟入栈,向服务器发送消息channel.writeInbound(Message());}
}

2.LineBasedFrameDecoder行解析器

向pipeline中加入LineBasedFrameDecoder行解析器,会以换行符"\n"作为完整消息边界,不过着要求每一个完整消息的末尾都加上换行符作为

使用方法,请尝试理解下面源码

public class LineBasedFrameDecoderTes {//构造一个消息public static ByteBuf Massage(){StringBuilder msg = new StringBuilder();char c = 'a';for(int i=0;i<10;i++){msg.append(c);c++;}//加一个换行符,作为结束符msg.append("\n");//重复一次for(int i=0;i<10;i++){msg.append(c);c++;}//加一个换行符,作为结束符msg.append("\n");return Unpooled.copiedBuffer(msg.toString(), StandardCharsets.UTF_8);}public static void main(String[] args) {//网络通信测试类,可以模拟客户端向服务器发送消息,不用实现客户端和服务端,方便调试所用EmbeddedChannel channel = new EmbeddedChannel(//最大长度设置,如果到了1024还没有遇到结束符,那么会报错new LineBasedFrameDecoder(10),new SimpleChannelInboundHandler<ByteBuf>(){@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {//接收到消息,做输出处理int len = buf.readableBytes();byte[] msg = new byte[len];//Bytebuf中的数据读取到byte字节数组buf.readBytes(msg);//byte字节数组转换为String字符串并输出System.out.println(new String(msg,0,len));}});channel.writeInbound(Massage());}
}

3.LengthFieldBasedFrameDecoder

向pipeline中加入LineBasedFrameDecoder行解析器,以设置长度读取消息
,不过这要求数据以消息长度+消息体的形式发送,也即先告知服务器数据的长度,再发送完整的数据

参数设置:

1.maxFrameLength:消息最大字节长度
2.lengthFieldOffset:声明消息长度变量的偏移量(也即字节下标是多少)
3.lengthFieldLength:声明消息长度变量的字节大小(一般用int声明,4字节)
4.lengthAdjustment:调着消息体的其实位置,如果忽略一个字节就设置为1,不忽略设置为0
5.initialBytesToStrip:最终消息从头剥离几个字节

使用方法,请尝试理解下面源码

/*** LTC解码器要求:* 消息长度(int)+消息体一起发送*/
public class LengFiledBasedFrameDecoderTest {public static ByteBuf Message(){ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();StringBuilder sb = new StringBuilder();char c = 'a';for(int i=0;i<20;i++){sb.append(c);c++;}byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8);buf.writeInt(bytes.length);buf.writeBytes(bytes);return buf;}public static void main(String[] args) {EmbeddedChannel channel = new EmbeddedChannel(/*参数设置1.maxFrameLength:消息最大字节长度2.lengthFieldOffset:声明消息长度变量的偏移量(也即字节下标是多少)3.lengthFieldLength:声明消息长度变量的字节大小(一般用int声明,4字节)4.lengthAdjustment:调着消息体的其实位置,如果忽略一个字节就设置为1,不忽略设置为05.initialBytesToStrip:最终消息从头剥离几个字节**/new LengthFieldBasedFrameDecoder(1024,0,4,0,4),new SimpleChannelInboundHandler<ByteBuf>(){@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {int len = buf.readableBytes();byte[] msg = new byte[len];buf.readBytes(msg);System.out.println(new String(msg,0,len));}});channel.writeInbound(Message());}}

Netty框架之TCP粘包/半包解决方案相关推荐

  1. TCP 粘包半包 netty 编解码 三者关系

    1 何为粘包 / 半包? 对方一次性接收了多条消息这种现象,我们就称之为 粘包现象. 对方多次接收了不完整消息这种现象,我们就称之为 半包现象. 粘包的原因: 发送方发送的消息 < 缓冲区大小 ...

  2. 三、Netty的粘包半包问题解决

    一.定义 TCP 传输中,客户端发送数据,实际是把数据写入到了 TCP 的缓存中,粘包和半包也就会在此时产生.客户端给服务端发送了两条消息ABC和DEF,服务端这边的接收会有多少种情况呢?有可能是一次 ...

  3. Netty粘包/半包问题解析

    目录 一.什么是粘包/半包问题 二.TCP粘包/半包发生的原因 三.粘包/半包解决办法 四.Netty中粘包/半包解决示例 1. 采用固定长度数据包编解码方式 2. 采用特殊字符作为边界字符编解码方式 ...

  4. Netty如何解决粘包半包问题

    何为粘包 / 半包? 比如,我们发送两条消息:ABC 和 DEF,那么对方收到的就一定是 ABC 和 DEF 吗? 不一定,对方可能一次就把两条消息接收完了,即 ABCDEF:也可能分成了好多次,比如 ...

  5. 网络:什么是TCP粘包/半包?怎么解决这个问题

    在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...

  6. netty——黏包半包的解决方案、滑动窗口的概念

    黏包半包 滑动窗口 在深入理解黏包半包问题之前,先了解TCP的一个知识点--滑动窗口 我们都指定tcp是一种可靠的传输协议,这主要是因为在tcp中客户端给服务器端发送一条消息,要等待服务器端的应答,如 ...

  7. websocket是否需要处理粘包半包问题分析

    结论: ​ 不需要. 背景: ​ 公司通信涉及到websocket相关,我们都知道websocket是基于tcp的,而tcp是面向字节流的,是需要处理粘包半包问题的.那么websocket是否需要处理 ...

  8. 【Netty入门】TCP 粘包/拆包问题产生原因

    TCP粘包/分包问题的由来 因为TCP是以流的方式来处理数据,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送. 这样说可能比较抽象,下面举例来说明TCP拆包/粘包 ...

  9. Http 调用netty 服务,服务调用客户端,伪同步响应.ProtoBuf 解决粘包,半包问题.

    实际情况是: 公司需要开发一个接口给新产品使用,需求如下 1.有一款硬件设备,客户用usb接上电脑就可以,但是此设备功能比较单一,所以开发一个服务器程序,辅助此设备业务功能 2.解决方案,使用Sock ...

最新文章

  1. ISE中使用Notepad++的关联设置以及Notepad++的护眼设置(设置背景色)
  2. centeros php pgsql,centos php添加pgsql扩展
  3. 服务器做文件共享服务特点,服务器主机做共享文件
  4. 排查链接是否失效_如何进行移动站点流量排查?
  5. 列举ospf的5种报文类型_OSPF的5种报文类型
  6. Android开发笔记(二十七)对象序列化
  7. wmware下linux安装vmware tools步骤
  8. win10远程计算机或设备将不接收连接?
  9. 作业一:建立博客、自我介绍、速读教材、学习进度总结(1)
  10. 图像处理——alpha融合
  11. 常用正则表达式大全(Xss防范、sql注入、手机邮箱验证等等,持续补充~)
  12. Dm365 VPBE 后端模块讲解
  13. 上完选修计算机绘图课心得,计算机绘图学习心得体会.doc
  14. 事务的四大特性-ADID特性
  15. 必看!前辈们总结出的程序员找工作遇到的坑
  16. Epubor Ultimate for mac(mac电子书转换软件)
  17. Human-in-the-Loop Optimization of Exoskeleton Assistance Via Online Simulation of Metabolic Cost
  18. 液晶监控屏:大屏领域已占据主导地位
  19. 神经性脚臭案例整理(二)
  20. 爱因斯坦阶梯问题及寻找完全数问题

热门文章

  1. 在TCP端口筛选只允
  2. TUV莱茵深圳物联网技术评估中心10月正式启用
  3. 第四篇 安装系统与多重引导
  4. 由子网掩码字符串转换成长度前缀的代码示例
  5. Mathon 的快捷键
  6. vue 车牌号校验(含新能源)
  7. topm java cpu3.3_快讯:TOPM 3-0 XQ,TOPM强势压迫,势如破竹喜获三连胜
  8. 传说中的b站mac客户端(支持M1芯片、适配Big Sur)-bilibili mac客户端
  9. 【R语言】使用nnet过程中报错Error in eval(predvars, data, env) : object ‘naulong‘ not found
  10. 计算机考研英语一和英语二的区别,考研英语一和英语二的区别,考研党知道了吗?...