0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何让接收端知道发送端将要发送的字节流长度?

冬至配饺子 来源:多兰多 作者:Toranto 2022-08-19 09:33 次阅读

粘包现象展示

一上来就枯燥的文字,难免容易犯困,所以我先演示一下粘包现象:

pYYBAGL-5cuAOVptAACt-k3cEww678.pngpYYBAGL-5dKAQaAaAACFAIai1xo613.png

我们的预期是,服务端打印出hello,I am Toranto这两个字符串,两个字符串经编码之后的字节总长度为17个字节,但是我们看结果:

pYYBAGL-5eiAZO4uAAClEv3pYXI844.png

ps:b''是表示字节的意思,和我们之前用的f''(format)格式化用法是一样的,单、双、三引号一样。可以了解一下:

pYYBAGL-5fmAJFgWAADuKMsMuyQ976.png

好了回归粘包现象,我们看到上图,我们采用两次接收数据的方式,两次都接收20个字节,但是发送端发送的两次总字节只有17个字节长度,所以,tcp基于流式的协议,会先发送第一段字节到一个缓冲区,如果时间间隔很短,则tcp会等第二段字也发送到这个缓冲区再统一发送到接收端这边,两次内容的粘合没有达到我们预期的效果,这就是粘包现象。

粘包

粘包是一种现象,而且只有tcp会出现粘包现象,udp不会,这是基于tcp的

流式传输

导致的,tcp是传输数据流。

tcp会将数据量较小,且发送时间间隔较短的数据一起打包发送,那么这里所讲的时间较短是相比网络延迟来说的。比如我们两次发送间隔为0.00001s,那么网络延迟为0.001s,这个时候两次的数据就会打包发送,这是一种优化机制,但也就是这个优化机制导致粘包现象。

首先我们需要了解一下socket收发数据的原理:

pYYBAGL-5hOAUFCWAAB4BXjjpO0413.png


发送端可以是1K1K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因。

UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方send一条信息的时候,无论底层怎样分段分片,TCP协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。

例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看来,根本不知道该文件的字节流从何处开始,在何处结束。

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

此外,发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。

粘包解决

很遗憾,socket并没有给我们提供内置解决方法。

那我们需要如何解决?

问题的根源在于,接收端不知道发送端将要发送的字节流的长度。

我们可以基于此点想解决办法,如何让接收端知道发送端将要发送的字节流长度(提前获知)?

我们可以在发送端写一个提前告知的代码,并且在接收端循环判定,是否达到预定字节流长度,达到了再一并打印出来:

发送端和接收端(关键)要结合起来看:

poYBAGL-5liADeynAACWEief7aM603.pngpoYBAGL-5maASjQyAAC99PDfsRo576.png

接下来我把源码放上来,我加了一些判断条件:

poYBAGL-5pyAGUpLAAEN4Em8_V4145.pngpoYBAGL-5qKADGyrAACxqV0zfe0603.pngpYYBAGL-5qeAaPxNAADr_s6XptU956.png

演示一下结果:

pYYBAGL-5-uAA8XNAAFN4_KPLZM724.pngpYYBAGL-5_CAFcRvAABXEcoRNqU369.png



审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编解码
    +关注

    关注

    1

    文章

    138

    浏览量

    19341
  • 字符串
    +关注

    关注

    1

    文章

    552

    浏览量

    20156
  • 网络编程
    +关注

    关注

    0

    文章

    64

    浏览量

    9984
  • TCP协议
    +关注

    关注

    1

    文章

    83

    浏览量

    12005
收藏 人收藏

    评论

    相关推荐

    HDMI信号的接收发送与PD的DFP和UFP有对应关系吗?

    HDMI信号的接收发送与PD的DFP和UFP有对应关系吗? 例如:一作为HDMI的接收
    发表于 02-29 07:46

    使用lwip socket udp功能,开发板为客户时不能够接收服务器端发送过来的数据 ?

    请教下,使用 lwip socket udp 功能,开发板为客户时不能够接收服务器端发送过来的数据 ? 1,如果开发板为 服务器,收发都可以 2,如果开发板为 客户
    发表于 04-16 06:01

    TCP通信的接收发送字符串的这个原理是什么啊?谢谢!

    一个是 服务器的 接收部分,一个是 客户发送部分。发送部分是不是: 先发送字符串的 长度
    发表于 05-06 15:52

    can总线发送大于八个字节数据代码怎实现

    将要发送IP报文所以将要发送的数据远远大于8个字节……现在的思路就是构造一个新的数据帧,包含头和尾还有数据的
    发表于 06-17 14:32

    LWIP UDP如何发送长度超过1500字节的数据?

    环境:STM32F7 + FREERTOS + LWIP UDP在使用UDP发送数据时,发现发送长度比较大的数据时PC的网络助手收不到数据,一直找BUG,最后看到网上说UDP
    发表于 05-23 19:28

    ADF7***2***的收发切换发送要发两次接收接收正确

    ADI_YU,你好!我现在用ADF7***2***能实现简单的收发,但是在收发之间切换的时候,发送要发两次接收接收正确。经过简单的测试
    发表于 11-21 09:06

    如何解决lwip的netconn客户发送问题

    我的板子做客户,用的lwip,现在在与服务器连接成功后,发送有个问题1,在网络调试助手中设置20ms不停发送1字节,板子客户
    发表于 07-15 04:36

    CC2500不能接收发送数据

    发送前TXBYTES能读到写进TX_FIFO中的字节数,发送完成后读到的是0.发送接收两边
    发表于 03-27 10:22

    STA模式测试TCP客户发送数据,串口无法接收是什么原因?

    具体描述见:【HLK-M30试用体验】STA模式测试及问题​(1)电脑通过串口发送数据,TCP客户能收到。(2)但是TCP客户发送数据
    发表于 06-04 05:55

    如何在发送发送逗号?

    将使用逗号检测和对齐模块。但现在我有点困惑。如何在发送发送逗号? 如果我只是使用GTP传输PRBS并接收PRBS,我是否必须使用逗号来对齐字节
    发表于 06-10 08:56

    如何两片89C51实现串行通信,发送将0~f循环发送接收并在接收显示?

    如何两片89C51实现串行通信,发送将0~f循环发送接收并在
    发表于 09-30 06:27

    在消息列队中初始化时怎么知道发送消息的长度

    问题:假设串口1接收了200个字节,串口接收完成后,通过消息列队把这200个数据发送给处理线程1,线程1怎么知道串口中断发过来的是200个
    发表于 03-24 09:26

    STM32F4发送接收长度数据的判断

    STM32F4 串口收发使用DMA还是很方便的。但是配置DMA时需要配置数据长度,这一点对于发送来说可以预估计自己发送长度来配置DMA发送
    发表于 11-08 16:25 6005次阅读

    STM32串口的发送接收

    USART是STM32内部集成的硬件外设,可以根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可以自动接收RX引脚的数据帧时序,拼接成一个字节数据,存放在数据寄存
    的头像 发表于 11-10 16:04 665次阅读
    STM32串口的<b class='flag-5'>发送</b>和<b class='flag-5'>接收</b>

    字节流和字符流有什么区别?看完就知道

    字节流和字符流有什么区别?看完就知道字节流和字符流是Java I/O系统中的两个重要概念,用于处理输入和输出的数据。 首先,字节流是以字节
    的头像 发表于 12-09 14:57 936次阅读