9月26日学习内容整理:TCP协议的粘包现象

一:粘包现象的由来

TCP俗称流式协议,源源不断的发送数据

但是TCP协议有个特点,就是会把间隔时间很短并且数据量较小的一些数据合为一个大数据进行发送

这个特点对于发送端来说,如果连续发送几个数据量很小的数据流,那么TCP就会将它们合为一个大数据,接收端收到这个大数据就会不知道怎么解析,分不清数据的分布,这样就会出错。这就是发送端的粘包现象

对于接受端来说,即使发送端没有发生粘包现象,当发送端送来准确的数据流时,接受端并没有全盘接受,而是设置了接受数量的上限或者由于文件过大无法一次接受完或者接收端并不知道文件的大小,这时候剩下来的数据就会暂时存在内存中,可是当发送端再送来数据时就会滞留在之前遗留数据的后等待接受,这时接收端想要接受后面的数据是取不出来的,这就是接收端的粘包现象,原因就是接收端对数据大小的未知

重要重要重要::::粘包现象的根源在于接收端一方对数据流的大小长度分布都不明确,导致无法处理粘包数据

 

补充:

1、subprocess模块:用于执行系统命令

obj  =   subprocess . Popen(系统命令(必须是字符串形式),shell = True , stdout=subprocess . PIPE , stdin =subprocess . PIPE , stderr = subprocess . PIPE )

shell代表是调用当前系统命令解释器

stdout 代表标准准确输出,PIPE表示一个管道,是想命令结果存到这样一个管道里,而不是打印到屏幕上

stdin  代表标准输入,也是将输入的内容存到管道里

stderr  代表标准错误输出,是将命令输入错误时显示的结果存在管道里,而不是直接打印到屏幕上

obj . stdout.read()   将正确的命令结果从管道中取出来,输出的是字节类型

obj . stderr.read()    将错误的命令结果从管道里取出来,输出的是字节类型

注意因为是执行的系统命令,所以结果肯定是以当前系统默认的编码存储的,所以要想转化为字符串,就必须以相应的系统编码转换

 

 

二、对粘包的处理

1、思路:

(1)第一种思路:发送端传送数据前先发送当前数据的长度以供接受端分辨

(2)第二种思路:若能将数据的长度封装在数据的固定长度包头里,这样数据端先接受包头的固定长度,再循环接受具体的数据内容,再依据接受到的的长度对数据长度进行判断就可以接受完整的数据流了

(3)第三种思路(最终的解决办法):因为数据的长度有大有小,非常大的数据长度可能无法包装在固定的数据头部里,并且数据头部也不一定只有长度信息,所以这时就想到把数据头部写成字典类型,在序列化成字符串,再转为字节类型,这个字节长度应该不会特别特别大,这样长度问题就解决了。然后将这个字节长度包装在固定长度的数据头部中,发送时先发送这个固定长度的数据头(接收端就知道字节的长度了),再发送字节数据(这时接收端就按照之前接受的长度接受),最后发送具体数据。这样接受端就完整的接受到了这个字节类型,再转换为字符串,再反序列化为字典,就得到数据头部的具体内容,在从中提取数据长度或者其它信息,再按照数据长度循环接受就得到完整准确的数据了

2、思路实现:

第一种思路弊端太大,不采用

第二种和第三种思路合起来。就要用到  struct   模块

struct模块

(1)打包:obj = struct . pack(' i ' , 数字)  i就代表是整型格式,把这个数字转为字节类型并固定在4个字节

(2)解包: struct . unpack(' i ' , obj) 也要指定整型格式,把打包好的obj对象解析出来,输出的是元组 (45,)类似这样,45就代表被打包的数字,通常后面加上索引0 [0] 取到这个被打包的数字

(3)格式为整型时,数字的范围是有限制的,所以引出了第三种思路

 

posted @ 2017-09-26 15:46  九二零  阅读(97)  评论(0编辑  收藏  举报