python 粘包解决方法
问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据。
简单的解决方法
这种方法的缺陷是程序的运行速度远快于网络传输速度,所以在发送一段字节前,先用send去发送该字节流长度,这种方式会放大网络延迟带来的性能损耗。
高级一点的解决方法
为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
struct模块
该模块可以把一个类型,如数字,转成固定长度的bytes
importjson,struct
#假设通过客户端上传1T:1073741824000的文件a.txt
#为避免粘包,必须自定制报头
header={'file_size':1073741824000,'file_name':'/a/b/c/d/e/a.txt','md5':'8f6fbf8347faa4924a76856701edb0f3'}#1T数据,文件路径和md5值
#为了该报头能传送,需要序列化并且转为bytes
head_bytes=bytes(json.dumps(header),encoding='utf-8')#序列化并转成bytes,用于传输
#为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节
head_len_bytes=struct.pack('i',len(head_bytes))#这4个字节里只包含了一个数字,该数字是报头的长度
#客户端开始发送
conn.send(head_len_bytes)#先发报头的长度,4个bytes
conn.send(head_bytes)#再发报头的字节格式
conn.sendall(文件内容)#然后发真实内容的字节格式
#服务端开始接收
head_len_bytes=s.recv(4)#先收报头4个bytes,得到报头长度的字节格式
x=struct.unpack('i',head_len_bytes)[0]#提取报头的长度
head_bytes=s.recv(x)#按照报头长度x,收取报头的bytes格式
header=json.loads(json.dumps(header))#提取报头
#最后根据报头的内容提取真实的数据,比如
real_data_len=s.recv(header['file_size'])
s.recv(real_data_len)
我们可以把报头做成字典,字典里包含将要发送的真实数据的详细信息,然后json序列化,然后用struck将序列化后的数据长度打包成4个字节(4个字节足够用了)
发送时:
先发报头长度
再编码报头内容然后发送
最后发真实内容
接收时:
先收报头长度,用struct取出来
根据取出的长度收取报头内容,然后解码,反序列化
从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容
以上内容为大家介绍了python粘包解决方法,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。

相关推荐HOT
更多>>
python cmd中怎么运行python文件
运行Python,可在交互模式下运行,或者命令行中。命令行中运行的是Python的.py文件。cmd中执行Python程序的方法,如下打开cmdC:\Users\Administ...详情>>
2023-11-06 14:37:04
pythondict是啥意思
Python中的dict表示的字典数据类型。字典是另一种可变容器模型,且可存储任意类型对象。字典是python语言中唯一的映射类型映射类型对象里哈希值...详情>>
2023-11-06 13:56:05
python如何创建模块
Python模块(Module),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句。模块让你能够有逻辑地组织你的Python代码段。把相关的...详情>>
2023-11-06 13:36:31
python解释器写代码如何换行
使用以下方法可以使Python的代码换行:用反斜杠链接多行代码,示例输出:55a=22+\33printa用小括号括起来,示例输出:55a=(22+33)printa提示:针...详情>>
2023-11-06 13:17:12热门推荐
技术干货






