python 粘包解决方法

发布时间:2022-05-09 09:47:07 人气:71 作者:多测师

  问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据。

  简单的解决方法

  这种方法的缺陷是程序的运行速度远快于网络传输速度,所以在发送一段字节前,先用send去发送该字节流长度,这种方式会放大网络延迟带来的性能损耗。

  高级一点的解决方法

  为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据

  struct模块

  该模块可以把一个类型,如数字,转成固定长度的bytes

  import json,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,用于传输

python 粘包解决方法

  #为了让客户端知道报头的长度,用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相关知识,请关注多测师。https://www.e70w.com/xwzx/


上一篇:python 进程池
下一篇:python 冒泡排序
返回列表
在线客服
联系方式

热线电话

17727591462

上班时间

周一到周五

二维码
线