Netty 粘包 拆包

粘包和半包定义如下:

  1. 粘包和半包,指的都不是一次是正常的 ByteBuf 缓存区接收。

  2. 粘包,就是接收端读取的时候,多个发送过来的 ByteBuf “粘”在了一起。

    换句话说,接收端读取一次的 ByteBuf ,读到了多个发送端的 ByteBuf ,是为粘包。

  3. 半包,就是接收端将一个发送端的ByteBuf “拆”开了,形成一个破碎的包,我们定义这种 ByteBuf 为半包。
    换句话说,接收端读取一次的 ByteBuf ,读到了发送端的一个 ByteBuf的一部分,是为半包。

粘包和半包 图解
上面的理论比较抽象,下面用一幅图来形象说明。

下图中,发送端发出4个数据包,接受端也接受到了4个数据包。但是,通讯过程中,接收端出现了 粘包和半包。
在这里插入图片描述
接收端收到的第一个包,正常。

接收端收到的第二个包,就是一个粘包。 将发送端的第二个包、第三个包,粘在一起了。

接收端收到的第三个包,第四个包,就是半包。将发送端的的第四个包,分开成了两个了。

粘包和半包原理,这得从底层说起。

在操作系统层面来说,我们使用了 TCP 协议。

在Netty的应用层,按照 ByteBuf 为 单位来发送数据,但是到了底层操作系统仍然是按照字节流发送数据,因此,从底层到应用层,需要进行二次拼装。

操作系统底层,是按照字节流的方式读入,到了 Netty 应用层面,需要二次拼装成 ByteBuf。

这就是粘包和半包的根源。

在Netty 层面,拼装成ByteBuf时,就是对底层缓冲的读取,这里就有问题了。

首先,上层应用层每次读取底层缓冲的数据容量是有限制的,当TCP底层缓冲数据包比较大时,将被分成多次读取,造成断包,在应用层来说,就是半包。

其次,如果上层应用层一次读到多个底层缓冲数据包,就是粘包。

如何解决呢?

基本思路是,在接收端,需要根据自定义协议来,来读取底层的数据包,重新组装我们应用层的数据包,这个过程通常在接收端称为拆包。

拆包的原理
拆包基本原理,简单来说:

接收端应用层不断从底层的TCP 缓冲区中读取数据。

每次读取完,判断一下是否为一个完整的应用层数据包。如果是,上层应用层数据包读取完成。

如果不是,那就保留该数据在应用层缓冲区,然后继续从 TCP 缓冲区中读取,直到得到一个完整的应用层数据包为止。

至此,半包问题得以解决。

如果从TCP底层读到了多个应用层数据包,则将整个应用层缓冲区,拆成一个一个的独立的应用层数据包,返回给调用程序。

至此,粘包问题得以解决。

Netty 中的拆包器
拆包这个工作,Netty 已经为大家备好了很多不同的拆包器。本着不重复发明轮子的原则,我们直接使用Netty现成的拆包器。

Netty 中的拆包器大致如下:

  1. 固定长度的拆包器 FixedLengthFrameDecoder

每个应用层数据包的都拆分成都是固定长度的大小,比如 1024字节。

  1. 行拆包器 LineBasedFrameDecoder

每个应用层数据包,都以换行符作为分隔符,进行分割拆分。

  1. 分隔符拆包器 DelimiterBasedFrameDecoder

每个应用层数据包,都通过自定义的分隔符,进行分割拆分。

这个版本,是LineBasedFrameDecoder 的通用版本,本质上是一样的。

  1. 基于数据包长度的拆包器 LengthFieldBasedFrameDecoder

将应用层数据包的长度,作为接收端应用层数据包的拆分依据。按照应用层数据包的大小,拆包。这个拆包器,有一个要求,就是应用层协议中包含数据包的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值