粘包现象展示
一上来就枯燥的文字,难免容易犯困,所以我先演示一下粘包现象:
我们的预期是,服务端打印出hello,i am toranto这两个字符串,两个字符串经编码之后的字节总长度为17个字节,但是我们看结果:
ps:b''是表示字节的意思,和我们之前用的f''(format)格式化用法是一样的,单、双、三引号一样。可以了解一下:
好了回归粘包现象,我们看到上图,我们采用两次接收数据的方式,两次都接收20个字节,但是发送端发送的两次总字节只有17个字节长度,所以,tcp基于流式的协议,会先发送第一段字节到一个缓冲区,如果时间间隔很短,则tcp会等第二段字也发送到这个缓冲区再统一发送到接收端这边,两次内容的粘合没有达到我们预期的效果,这就是粘包现象。
粘包
粘包是一种现象,而且只有tcp会出现粘包现象,udp不会,这是基于tcp的
流式传输
导致的,tcp是传输数据流。
tcp会将数据量较小,且发送时间间隔较短的数据一起打包发送,那么这里所讲的时间较短是相比网络延迟来说的。比如我们两次发送间隔为0.00001s,那么网络延迟为0.001s,这个时候两次的数据就会打包发送,这是一种优化机制,但也就是这个优化机制导致粘包现象。
首先我们需要了解一下socket收发数据的原理:
发送端可以是1k1k地发送数据,而接收端的应用程序可以两k两k地提走数据,当然也有可能一次提走3k或6k数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此tcp协议是面向流的协议,这也是容易出现粘包问题的原因。
而udp是面向消息的协议,每个udp段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和tcp是很不同的。怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方send一条信息的时候,无论底层怎样分段分片,tcp协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。
例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看来,根本不知道该文件的字节流从何处开始,在何处结束。
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
此外,发送方引起的粘包是由tcp协议本身造成的,tcp为提高传输效率,发送方往往要收集到足够多的数据后才发送一个tcp段。若连续几次需要send的数据都很少,通常tcp会根据优化算法把这些数据合成一个tcp段后一次发送出去,这样接收方就收到了粘包数据。
粘包解决
很遗憾,socket并没有给我们提供内置解决方法。
那我们需要如何解决?
问题的根源在于,接收端不知道发送端将要发送的字节流的长度。
我们可以基于此点想解决办法,如何让接收端知道发送端将要发送的字节流长度(提前获知)?
我们可以在发送端写一个提前告知的代码,并且在接收端循环判定,是否达到预定字节流长度,达到了再一并打印出来:
发送端和接收端(关键)要结合起来看:
接下来我把源码放上来,我加了一些判断条件:
演示一下结果:
旷视科技Face为何能成为人工智能“独角兽”之首
曾第一大民营宽带运营商退出宽带市场,未来宽带市场将如何变化
单立柱码垛机的结构布造
为PCB和SMT行业提供激光技术解决方案
openGauss企业级开源数据库获CITE 2022“金奖”
如何让接收端知道发送端将要发送的字节流长度?
基于WT2003H的语音压力传感器应用设计方案
德勤研究:企业将5G和Wi-Fi6作为新兴技术的“力量倍增器”
CES | Ada 架构突破能效边界,为玩家和创作者打造的 170 多款笔记本电脑提供超强动力
KJN4逆变换相板原理图
智能电子车牌及未来的发展趋势
扎心了华为!iPhone8最新谍照:有疏油层,生活防水
关于新一代无线WiFi6的简单介绍
5-100v电流倒灌和高边开关的解决方案介绍
iPhone8什么时候上市?iphone7s/iphone 8即将发布,真机曝光,带来腮红金新配色,功能牛,价格更牛
波音公司透露737MAX飞机将于6月底或7月复飞
浅谈云计算环境中的容量管理挑战
圆柱电阻特点_圆柱电阻应用
工业边缘智能网关可满足各种工业应用场景
在Microzed上构建嵌入式linux系统(ubuntu16.04下)