坦白局,TCP粘包:我只是犯了每个数据包都会犯的错

      最后更新:2022-06-24 04:55:37 手机定位技术交流文章

      让我们从健身教练开始吧。

      李东声称自己是次诊的终结者,试图利用互联网+模式扩大自己的业务。 广告在新开发的聊天软件中发表。

      键盘走来走去。 疯狂的发送“李东”, 把车送回!, “不健康的终结者”, 把车送回!

      还记得四层网络协议是什么样子 吗?

      每个层次的四个层次网络模型功能,每个层都添加了多个标题的讯息,多个标题可以被理解为多个数据标题的帽子。头条记录了消息的来源,到哪去,以及消息的长度。比如,麦克头记录是硬件唯一的地址,从哪里到哪里记录的IP头,传输层记录了到达目标主机后要进行哪些过程。

      当消息被发送到网络时,消息被报告在消息带上,消息和复杂的网络通过这些信息在路由器之间循环,最终到达目标机器,接收者再次通过这些消息,逐步返回发送者发送的最原始消息。

      为什么要将数据切片

      软件在应用程序一级。

      两个消息,Li Dong和Sub-HealthTerminator,在进入传输层时使用传输层的TCP协议。

      你可以把网络比作水管,是有一定的粗细的,这种粗糙度由网络接口层(数据链层)提供给网络层,MTU(1500),一般考虑,直接传入整个消息,超过水管的最大容忍度,那么,就需要进行切片,成为一个个数据包,这些信息通常可以通过“水管”传递。

      MTU和MSS之间的区别是什么?

      • MTU: Maximum Transmit Unit,最大传输单元。通过网络接口层(数据链层)向网络层传输的数据的大小,最大为一个传输;通常MTU=1500 Byte。 假设IP层有 <= 1500 byte 需要发送,只需要一个 IP 包就可以完成发送任务;假设 IP 层有> 1500 byte 数据需要发送,完成传输需要一张纸,分开后IP字节ID是相同的。
      • MSS:Maximum Segment Size。将TCP提交到IP层的最大分段大小,不包括TCP头条和TCP选项,只包括TCP收费,MSS是一个用于限制应用程序层发送字节的最大数量的TCP。假设MTU=1500字节,所以MSS=1500-20(IP字节)-20(TCP字节)=1460字节,如果应用程序层需要发送200字节,然后需要两件来完成传输,第一个TCP芯片=1460,第二个TCP芯片 = 540.

      什么是粘包

      因此,当李东在手机上输入“李东”,在TCP中将消息分成MSS大小后,消息通过网络发送。

      网络非常安全,发送消息片段到手机的另一端B.A TCP级消息被重新组织,成为像"Lee East Asian Health Terminator"这样的字流。

      但因为聊天软件陈陈刚开发,而且开发者叫小白,完了,一个臭名昭著的虫工。经过他的代码,处理节点流时,"李东"的讯息,“健康终结”成了“李东亚洲”,"健康终结者"。“李东”作为前面的包的内容和下一个包的“A”粘在一起被误解为数据包。这就是所谓的粘包。

      一位已知的终生健身教练,也许不会太幸运,让我们祝他晚安。

      为什么会出现粘包

      那么,你所说的TCP是什么意思?

      TCP,传输控制协议(英语:Transmission Control Protocol) 传输控制协议(英语:Transmission control protocol)是一种面向连接、可靠、基于字节流的传输层通信协议。

      粘剂的最重要的关系是基于字节流的特点.

      数据流可以理解为数据流通过双向通道,我们通常称之为二进制数据,只是一组01字符串。

      应用程序层将数据发送到TCP协议上,不是以单元发送消息到目标主机,而是以字节流向下发送数据,数据可以切断并组装成各种数据包,接收者接收这些数据包而不正确地恢复原始消息,导致粘贴的数据包现象。

      为什么汇集发送的数据

      上面提到的TCP切断数据包的目的是能够顺利通过网络通过水管。 相反,有组装的情况。 如果由TCP发送的数据比MSS要小得多,例如几个字节,每个字节分别发送这些字节,就是一种网络废物。

      例如,小白爸爸放小白出去买一瓶大豆酱,小白出去买大豆酱回来。 小白妈妈放小白出去买一瓶醋回来。 小白在比赛前后完成两场比赛,影响了比赛时间。

      当小白的爸爸要求小白买大豆酱时,小白先等着,继续玩游戏,当小白的妈妈要求小白再买一瓶醋时,小白可以同时带两个要求,然后把东西带回来。

      以上实际上是TCP的纳格尔算法优化,旨在避免发送小数据包。

      当Nagle算法打开时,在下列两个条件下将发送数据包:

      • 如果数据包长度达到MSS(或包含Fin数据包),立即发送,否则等待下一个数据包到达;如果下两个数据包的总长度超过MSS,则执行分发发送;
      • 等待过时(通常是200ms),第一个数据包不会达到MSS长度,然后等待到第二个数据包到达并立即发送。

      • 自从纳格尔算法推出以来,msg1比mss小,一个msg2在200ms的等待中到达,msg1 + msg2 > MSS,因此,把msg2分成msg2(1)和msg2(2),msg1+msg2(1)包的大小是MSS。此时发送出去。
      • 其余的 msg2(2)也等待 msg3, 同样 msg2(2) + msg3 > MSS,因此,把msg3分成msg3(1)和msg3(2),msg2(2) + msg3(1)被发送为一包。
      • 剩余的 msg3(2) 不等于 mss, 并不会在200 ms 内等待下一包, 等待过时, 并直接发送.
      • 现在,虽然这三个包装在图中颜色不同,但是实际场景中,他们都是一组01,如果处理器将第一个收到的 msg1 + msg2(1) 作为完整的消息处理,看起来像两个袋子粘在一起,就会导致粘包问题。

      纳格尔算法不会被粘接 吗?

      纳格尔算法实际上是几年的,于1984年诞生。 一个应用程序每次发送一个字节数据的场景,没有纳格尔优化,这些数据包被发送出去,导致网络因太多数据包而过载。

      但今天网络环境比以前好多了,纳格尔的优化帮助并不那么大。而且它的延迟发送,有时它也会导致调用延迟的延长,比如打游戏的时候,你操作如此丝滑,但是由于纳格尔算法延迟了传输,结果是比特慢了,就问你难受不难受。

      所以现在通常是关掉。

      看来,纳格尔算法的优化并不十分有效,也会导致粘贴问题。 因此,是否可以关闭该算法来解决包装问题?

      TCP_NODELAY = 1

      • 当接收MSg1时,接收端应用程序层被删除,因此当时MSg1没有粘贴问题
      • **msg2 **之后,应用程序层很忙,不能把它关掉,所以它留在TCP Recv缓冲器中
      • **msg3 **现在是把msg2和msg3放在TCP Recv缓冲器里的时候了
      • 此时应用程序层很忙,要获取数据,在图中有两个颜色区分,但在实际场景中有01个字符串,此时可以一起拿走,找到或粘贴。

      因此,即使纳格尔算法关闭,接收数据端的应用程序层不会及时读取TCP Recv缓冲器中的数据,并且会有一个缓冲器。

      怎么处理粘包

      sticking 的 根本 原因 是 信息 的 界限 不确定 。当接收器面对“无限”的二进制流时**,我不知道我有多少01来数一个消息。如果你不小心拿太多了, 它会粘着.事实上,粘剂不是TCP问题,这是用户对TCP理解的一个错误。

      只要接收机在每次发送给发送者时在消息带上识别消息边界信息,接收机可以相应地识别消息的边界,从而区分每个消息。

      常见的方法有

      • 加入特殊标志

      你可以用一个特殊的标记作为标题,例如,当你得到一张0xffe或返回票时,我想我得到了新闻的头条,此时继续取数据,到下一个头标0xffe或尾标收到为止,把它当作一个完整的信息.类似地,在HTTP协议中,当用于分块编码传输时,使用多个块组件消息,最后以0的长度标记的块结束。

      • 加入消息长度信息

      这通常与上面的特殊符号结合起来。在收到头标志时,也可以把消息的长度加进去,这表明该消息之后有多少字节属于该消息。如果有一个字节与此后的长度匹配,则取走,使用为应用程序层的完整消息。在实际场景中,HTTP中的内容长度也有类似的作用,当接收者接收的消息小于内容长度时,尚 没有 收到 某些 资料 。那接收端会一直等,直到我们有足够的新闻或加班,本文对此进行了更详细的描述。

      也许在这一点上,朋友会问你,如果你使用0xffe来标记一个包的开端,你难道不担心你发送的一些数据有相同的内容吗?

      是的,我担心,所以通常除了这个标记点之外,发送者在发送消息后在标记点后面添加一些检查字段(在整个数据上取得的检查和/或数据)并确保它是发送者在接收者得到完整的数据后发送的完整的数据。

      UDP 会粘包吗

      它与TCP、UDP和User Datagram协议相同。 用户包协议是无连接、不可靠和基于数据的传输层通信协议。

      基于数据的报告(Data Based Reporting)指多个报告到UDP, 不管应用程序层.UDP也同样发送,也就是说, 只发送一次消息.如果这个包太长,需要分片,这也是IP层。大不了效率低一些。UDP向应用程序层报告,既不合并,也不拆分,相反, 这些 报告 的 界限 仍然 存在 。当接收器接收数据消息时,当它结束时,它不会像面对无限的TCP二进制流那样清晰。由于数据报告和节点流之间的差异,TCP将10字节的流数据发送到终端上,此时,接收器可以接收数据100次,每个数据检索的长度可以根据处理能力调整;但UDP发送10份数据报告,接收器将完成10次。且发了多少,就取多少,确保每次有完整的数据报告。

      我们先看下IP报头

      注意,这包含16位的总长度,这意味着IP包的总长度被记录在IP标题中,然后我们再看UDP标题。

      在标题中,16位用于表示UDP数据消息的长度,假设这个长度是n,以此作为数据边界。因此,接收端的应用程序层可以清晰地区分不同的数据消息,从头条开始,取 n 个位置,这是一个完整的数据报告,这避免了粘贴和包装的问题。

      当然,即使没有此位(16位UDP长度),因为IP的头 already contains the total length information of the data,如果用于发送数据到IP包(网络层)的协议是UDP(传输层),因此这个总长度实际上包含了UDP和UDP数据的头部。

      因为UDP的标题为8字节(1字节=8位元),8字节=64位元,在上述图中,除数据和选项外),因此,计算UDP数据的长度很容易。因此,UDP的长度信息实际上是冗余的。

      UDP数据长度 = IP总长度 - IP头部长度 - UDP头部长度

      你可以再看下面的TCP标题

      TCP头条没有与UDP类似的长度信息,也可以用下面的公式获取当前的包的TCP数据长度。

      TCP数据长度=IP总长度-IP字节长度-TCP字节长度。

      与UDP不同,TCP发送器并不保证在发送时发送一个完整的数据消息,而是只查看一个没有结构的节点字符串,即使接收者知道其长度,这些节点也并不有用,因为它们很可能是完整的消息的一部分。

      为什么长度字段冗余被添加到UDP头条

      关于这一点,查了很多资料,在TCP-IP解释(卷2)中,人们说它可能是因为它被用来计算校正和。也有人说,UDP的根本用途可能不是IP协议,毕竟,IP头的总长度,它可以用于计算UDP数据的长度,如果UDP底层不是IP层协议,代替其他网络层协议,你不能继续做这种计算。

      但我觉得,最重要的原因是,IP层是网络层,UDP是传输层,到了传输层,该包已经没有IP头条信息,然后将UDP数据存储在UDP的插座缓冲器中。当应用程序层未能取得该UDP数据报告时,因此这两个数据报告实际上是数据一级的01字符串的集合。此时,在阅读第一份数据报告时,先读到UDP头条,如果当前UDP头没有UDP长度信息,那么应用程序层需要多少数据来计算一个完整的数据报告?

      因此,UDP头的长度实际上与TCP添加到消息体的边界信息相同,以防止粘附。

      面试官可能会认为我特别喜欢思考, 增加和增加.

      如果我错了,请把我的文章传给更多的人,这样每个人都能记住这个满嘴胡言乱语的人,经过仔细的私人信 cursing me, 请!

      IP层有粘贴问题吗

      IP层切断了大的包, 有粘贴问题 吗?

      首先,结论。 首先,正如上面提到的那样,粘贴实际上是用户无法正确区分消息边界所造成的问题。

      让我们先看看IP层的芯片包装.

      • 如果消息太长,IP层将消息按MTU长度分成N个部分,每个部分都有自己的偏差和相同的IP标题信息。
      • 每个芯片通过网络传输,每个数据包芯片可以通过不同的路由器流动,并在最后的端点合并后重新组装。
      • 当接收器接收第一个芯片数据包时,它将申请一个新的内存,创建一个IP数据包结构,然后等待其他芯片数据包的安装。
      • 一旦所有消息都存在,整个消息包被处理到上层(传输层)。

      可以看到整个过程,从IP层到剪切的长度到将剪切成数据包的组装,只处理传输,不关心消息的边界和内容,不关心消息的内容,那么就不会有粘贴的包。

      IP层意味着:我只是把数据从传送机转到接收机,而我不知道发生什么事。

      听起来像“我不在乎产品的需求,我已经做到了正确的事,我不问,而且我懒得争论,”这是值得每一个优秀的潜水程序员学习的思考,尊重的。

      总结

      sticking 问题的原因在于开发人员不正确理解TCP 导向数据传输的方式,这本身不是 TCP 问题,而是开发人员的问题。

      • TCP将数据发送给接收机,不管接收机想发送什么。 这个字节流可能包含一些关于你希望先发送的数据的信息。 接收机随需要添加消息边界信息。
      • TCP粘附与纳格尔算法有关,但关闭纳格尔算法不会解决粘附问题。
      • UDP是一个基于数据的传输协议,没有粘贴问题。
      • IP层也被切断,但因为它不在乎消息中的内容,所以没有粘性问题。
      • TCP发送器可以发送10个数据流,接收器可以接收100个;UDP发送器发送10个数据消息,接收器接收10次。

      数据包也通过TCP简单地组装和解压缩,如果数据包是错误的,那么数据包就犯了每个数据包所犯的错误。

      最后,小白说,李东失业了

      作者:9號同学
      链接:
      https://juejin.cn/post/6942640423286341668
      来源:掘金

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/28275.html

          热门文章

          文章分类