计算机网络:TCP粘包拆包以及通信协议

目录

前言

一、粘包和拆包是什么?

二、粘包拆包的解决方案

Netty对于粘包拆包的解决方案

编解码

解码器

编码器

总结



前言

在学习Java网络编程的过程中,除了TCP/IP的传输协议外,在TCP的传输过程中会遇到粘包和拆包的问题,而一般我们会使用特定的通信协议去解决粘包与拆包问题,所有在这里就对这两方面的知识进行学习和讲解。


一、粘包和拆包是什么?

由于TPC是面向连接以字节流的形式进行传输的。并且它没有设定保护边界,并且在字节流传输的过程中,操作系统会设置一个缓冲区来进行优化。

那么,当我们发送的数据大小较小,没有达到缓冲区设置的大小的时候,TCP就会将多个请求合并成一个请求进行发送,这就是粘包现象。

而当我们发送的数据大小较大,超过了缓冲区设置的大小,那么就会将这个数据分成多个请求进行发送,这就是拆包现象。

这里借用知乎用户@程序新视界的图片

计算机网络:TCP粘包拆包以及通信协议_第1张图片

上面途中分别发生了以下几种情况。

理想状态下,packet1 和packet2的大小恰好满足满足缓冲区的大小,或者packet1和packet2的发送间隔时长满足TCP的等待时长,所有就是正常的两个请求数据包发送。 

粘包状态,packet1和packet2由于大小较小,发送间隔时间又短,所以合并成一个包发送

拆包状态下,一个packet1包大小过大,拆分成了三个数据包发送。

还有就是拆分的包又和其它的包发生了粘包这种情况

这里可能大家会有疑问,为什么TCP会发生粘包拆包,而UDP不会呢。

粘包拆包在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中。

二、粘包拆包的解决方案

对于粘包和拆包问题,常见的解决方案有四种:

  • 发送端将每个包都封装成固定的长度,比如100字节大小。如果不足100字节可通过补0或空等进行填充到指定长度;
  • 发送端在每个包的末尾使用固定的分隔符,例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并;例如,FTP协议;
  • 将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息;
  • 通过自定义协议进行粘包和拆包的处理。

Netty对于粘包拆包的解决方案

首先我们了解一下编解码的概念

编解码

在网络通信中,将数据转成报文的过程称为 编码,将报文转成数据的过程称为 解码
在 Netty 中,编解码的处理放在 PipeLine 中。每个 PipeLine 都是和 Channel 唯一绑定的,一个 PipeLine 只对应一个 Channel,所以 Channel 中的数据读取的时候经过解析,如果不是一个完整的数据包,则解析失败,将这个数据包进行保存,等下次解析时再和这个数据包进行组装解析,直到解析到完整的数据包,才会将数据包向下传递。

解码器

Netty提供了多个解码器,分别是:

  1. LineBasedFrameDecoder:以行为单位进行数据包的解码;
  2. DelimiterBasedFrameDecoder:以特殊的符号作为分隔来进行数据包的解码;
  3. FixedLengthFrameDecoder:以固定长度进行数据包的解码;
  4. LenghtFieldBasedFrameDecode:适用于消息头包含消息长度的协议(最常用);

在 RPC 远程调用的场景中,我们来分析一下我们应该选哪种解码器:

  1. LineBasedFrameDecoder:按行分包显然不行,因为我们的请求响应数据中,极有可能包含换行符。
  2. DelimiterBasedFrameDecoder:按照特殊分隔符也不行,因为 RPC 框架是一个通用的场景,请求响应数据中什么都有可能包含,特殊分隔符无论是什么都有可能存在于请求响应数据中。这样会导致分包错误。
  3. FixedLengthFrameDecoder:使用定长报文显然就更加不合适了,在 RPC 框架这样一个通用场景中,定的长度太短,可能不够,定得太长又会造成极大的资源浪费。
  4. LengthFieldBasedFrameDecoder:将消息分成消息头消息体的方式比较使用于大部分的网络通信场景。所以我们一般使用这种自定义的方式来设计通信协议。

编码器

Netty 提供了个常用的抽象编码器:MessageToByteEncoder,编码器不像解码器需要考虑粘包拆包,只需要将数据转换成协议规定的二进制格式发送即可。


总结

理解TCP的粘包,拆包机制可以帮助我们更好的了解为什么通过一些基于TCP的网络传输框架会实现自己的通信协议。另外还了解了Netty是如何解决粘包拆包问题的。

你可能感兴趣的:(计算机网络,tcp/ip)