我的编程空间,编程开发者的网络收藏夹
学习永远不晚

一分钟看懂TCP粘包拆包

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

一分钟看懂TCP粘包拆包

比如说有一天你特别想喝奶茶,看了一下外卖,「一点点」的奶茶看着不错,(一点点赶紧给我打钱 doge),于是你在群里发了一条消息,想找几个人拼奶茶:

一点点奶茶有人喝吗?

结果群里同事回了一句:

现在不是已经三点了吗?

你觉得莫名其妙,看了一眼同事的手机,他收到的消息是这样的两行:

一点

点奶茶有人喝吗?

哈哈,讲了一个冷笑话。用专业的术语来说这种现象就是「拆包」了,我们接着往下讲。

TCP 粘包拆包的现象

粘包拆包问题一般是处于应用层下的问题,在数据链路层、网络层以及传输层都有可能发生。我们日常的网络应用开发大多都在传输层进行,因此本文着重讲解传输层粘包拆包问题。

传输层有两个协议我们都很熟悉:UDP 和 TCP,UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中。

下面用一个简单的例子来讲解什么是粘包和拆包。

假设客户端向服务端连续发送了两个数据包,用 packet1 和 packet2 来表示,那么服务端收到的数据可能有四种:

(1)第一种情况,服务端按顺序正常收到两个包,即未出现粘包和拆包的现象。

(2)第二种情况,服务端只收到一个数据包,由于 TCP 保证送达的特性,所以这一个数据包包含了客户端发送的两个数据包的信息,这种现象就是粘包。除非客户端发送的数据包有明确的规则,否则服务端不知道两个包的界限,难以处理数据。

(3)第三种情况,服务端收到了三个数据包,Package1数据包被拆分为两个数据包:Package1.1和Package1.2,这种现象就是拆包,至于拆包的原因下面会讲,服务端收到拆开的数据包也很难处理。

(4)第四种情况,一些大的数据包被拆分为小的数据包,小的数据包与其他数据包粘在一起,这种现象是将上面的粘包和拆包综合在一块。

TCP 粘包拆包的原因

TCP 是一个面向「流」的协议,所谓流就是没有界限的一长串二进制数据。TCP 作为传输层协议并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整的包,可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就会出现粘包拆包的问题。

例如,TCP缓冲区是1024个字节大小,如果应用一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,站在业务上来看这就是「粘包」;

如果应用一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是「拆包」,也就是将一个大的包拆分为多个小包进行发送。

TCP 粘包拆包的解决方法

TCP 是面向流的,会发生粘包和拆包,那作为应用程序,如何从这源源不断涌来的数据流中拆分出或者合并出有意义的信息呢?通常会有以下一些常用的方法:

(1)发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

如下图,在每个包前面加上包的实际长度。

(2)发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

下图每个包的固定长度为 4,接收端很容易进行区分。

(3)可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

如下图,在每个包的后面加上特殊字符:/

Netty 框架如何解决粘包拆包问题

Netty 作为一款高性能的 Java 网络编程框架,不仅是基于 Java NIO 进行了深度封装,还在客户端与服务端之间的数据传输上做了有效处理。

前面讲过 TCP 传输会出现粘包和拆包的现象,Netty 针对这一点内置了多款数据流编解码器,客户端服务端按照约定好的规则进行数据传输即可解决这个问题。

Netty 提供了多款开箱即用的编解码器:

(1)FixedLengthFrameDecoder 固定长度解码器

(2)DelimiterBasedFrameDecoder 指定分隔符解码器

(3)LengthFieldBasedFrameDecoder 基于数据包长度解码器

(4)等等……这里不再列举

小结

TCP 是一个面向「流」的协议,所谓流就是没有界限的一长串二进制数据。在实际的传输过程中,TCP 会根据网络情况将数据包进行拆分或者拼装,如果业务没有定义一个明确的界限规则,在应用层的业务上就会出现粘包拆包的现象。

针对 TCP 粘包拆包的现象,常见的解决思路如下:

(1)发送端给每个数据包添加包首部。

(2)发送端将每个数据包封装为固定长度。

(3)可以在数据包之间设置边界。

为了解决粘包拆包,Netty 框架也提供了很多开箱即用的编解码器,极大简化网络编程解决此类问题的难度。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

一分钟看懂TCP粘包拆包

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

一分钟看懂TCP粘包拆包

TCP 是一个面向「流」的协议,所谓流就是没有界限的一长串二进制数据。在实际的传输过程中,TCP 会根据网络情况将数据包进行拆分或者拼装,如果业务没有定义一个明确的界限规则,在应用层的业务上就会出现粘包拆包的现象。

你真的理解粘包与半包吗?三分钟搞懂它

只有等接收到全部包裹时,这个东西(传输的信息)才完整,所以半包情况下无法解析出完整的数据,需要等,等接收到全部包裹。

五分钟看懂抓包神技:DPDK

我是一个网络监控软件,我被开发出来的使命就是监控网络中进进出出的所有通信流量。

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录