加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

TCP粘包、拆包与通讯协议详解

发布时间:2019-10-18 02:23:13 所属栏目:教程 来源:田守枝
导读:在TCP编程中,我们行使协议(protocol)来办理粘包和拆包题目。本文将详解TCP粘包和半包发生的缘故起因,以及怎样通过协议来办理粘包、拆包题目。让你知其然,知其以是然。 1 TCP粘包、拆包图解 因为TCP传输协议面向流的,没有动静掩护界线。一方发送的多个报文

将动静区分为动静头和动静体,在动静头中,我们行使一个整形数字,譬喻一个int,来暗示动静体的长度。而动静体现实现实要发送的二进制数据字节。以下是一个根基名目:

  1.  header    body 
  2. +--------+----------+ 
  3. | Length |  Content | 
  4. +--------+----------+ 

在变长协议中:

  • 发送方,发送数据之前,必要先获取必要发送内容的二进制字节巨细,然后在必要发送的内容前面添加一个整数,暗示动静体二进制字节的长度。
  • 吸取方,在理会时,先读取内容长度Length,其值为现实动静体内容(Content)占用的字节数,之后必需读取到这么多字节的内容,才以为是一个完备的数据报文。

提醒:Netty中提供了LengthFieldPrepender给现实内容Content举办编码添加Length字段,接管方行使LengthFieldBasedFrameDecoder解码。

3.4 序列化

序列化本质上已经不是为了办理粘包和拆包题目,而是为了在收集开拓中可以越发的便捷。在变长协议中,我们看到可以在现实要发送的数据之前加上一个length字段,暗示现实要发送的数据的长度。这现实上给我们了一个很好的思绪,我们完全可以将一个工具转换成二进制字节,来举办通讯,譬喻行使一个Request工具暗示哀求,行使一个Response工具暗示相应。

序列化框架有许多种,我们在选择时,首要思量序列化/反序列化的速率,序列化占用的体积,多说话支持等。下面列出了业界风行的序列化框架:

TCP粘包、拆包与通讯协议详解

提醒:xml、json也属于序列化框架的领域,上面的表格中并没有列出。

一些收集通讯的RPC框架凡是会支持多种序列化方法,譬喻dubbo支持hessian、json、kyro、fst等。在支持多种序列化框架的环境下,在协议中凡是必要有一个字段来暗示序列化的范例,譬喻,我们可以将上述变长协议的名目改革为:

  1. +--------+-------------+------------+ 
  2. | Length |  serializer |   Content  | 
  3. +--------+-------------+------------+ 

这里行使1个字节暗示Serializer的值,行使差异的值代表差异的框架。

发送方,选择好序列化框架后编码后,必要指定Serializer字段的值。

吸取方,在解码时,按照Serializer的值选择对应的框架举办反序列化;

3.5 压缩

凡是,为了节减收集开销,在收集通讯时,可以思量对数据举办压缩。常见的压缩算法有lz4、snappy、gzip等。在选择压缩算法时,我们首要思量压缩比以及解压缩的服从。

我们可以在收集通讯协议中,添加一个compress字段,暗示回收的压缩算法:

  1. +--------+-----------+------------+------------+ 
  2. | Length | serializer|  compress  |   Content  | 
  3. +--------+-----------+------------+------------+ 

凡是,我们没有须要行使一个字节,来暗示回收的压缩算法,1个字节可以标识256种也许环境,而常用压缩算法也就那么几种,因此凡是只必要行使2~3个bit来暗示回收的压缩算法即可。

其它,因为数据量较量小的时辰,压缩比并不会太高,没有须要对全部发送的数据都举办压缩,只有再高出必然巨细的环境下,才思量举办压缩。如rocketmq,producer在发送动静时,默认动静巨细高出4k,才会举办压缩。因此,compress字段,应该有一个值,暗示没有行使任何压缩算法,譬喻行使0。

3.6 查错校验码

一些通讯协议传输的数据中,还包括了查错校验码。典范的算法如CRC32、Adler32等。java对这两种校验方法都提供了支持,java.util.zip.Adler32、java.util.zip.CRC32。

  1. +--------+-----------+------------+------------+---------+ 
  2. | Length | serializer|  compress  |   Content  |  CRC32  | 
  3. +--------+-----------+------------+------------+---------+ 

这里并差池CRC32、Adler32举办具体声名,首要是思量,为什么必要举办校验?

有人说是由于思量到安详,这个来由好像并不充实,由于我们已经有了TLS层的加密,CRC32、Adler32的浸染不该该是为了思量安详。

一位同事的概念,我很是拥护:二进制数据在传输的进程中,也许由于电磁滋扰,导致一个高电平酿成低电平,可能低电平酿成高电平。这种环境下,数据相等于受到了污染,此时通过CRC32等校验值,则可以验证数据的正确性。

其它,凡是校验机制在通讯协议中,是可选的设置的,并不必要逼迫开启,其固然可以担保数据的正确,可是计较校验值也会带来一些特另外机能丧失。如Mysql主从同步,固然高版本默认开启CRC32校验,可是也可以通过设置禁用。

3.7 小结

本节通过一些根基的案例,讲授了在TCP编程中,怎样通过协议来办理粘包、拆包题目。在现实开拓中,凡是我们的协议会越发伟大。譬喻,一些RPC框架,会在协议中添加独一标识一个哀求的ID,一些支持双向通讯的RPC框架,如sofa-bolt,还会添加一个偏向信息等。虽然,所谓伟大,无非是在协议中添加了某个字段用于某个用途,只要弄清晰这些字段的寄义,也就不伟大了。

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读