• 解决粘包现象的思路和方法


    粘包就是传输数据时,数据在缓冲池中粘连,无法分开.

    为了解决粘包,就要知道发送方发送了多少数据,接受方就接收多少.区分开来

    但是,怎么知道数据的长度呢?就需要在传送数据的时候,先将要发送的字节数告诉接收方(而且这个数字还要是固定字节数,要不我读取的时候也会发生偏差)

    所以就用到了struct模块,它的功能是将,不同长度的数字,转换成固定字节数的bytes类型..

     1 import struct
     2 s = struct.pack("i", 1234)
     3 s1 = struct.pack("i", 12345)
     4 s2 = struct.pack("i", 123456)
     5 print(s, len(s))
     6 print(s1, len(s1))
     7 print(s2, len(s2))
     8 
     9 u = struct.unpack("i", s)
    10 u1 = struct.unpack("i", s1)
    11 u2 = struct.unpack("i", s2)
    12 print(u)
    13 print(u1)
    14 print(u2)

    结果对照:

    1 b'xd2x04x00x00' 4
    2 b'90x00x00' 4
    3 b'@xe2x01x00' 4
    4 (1234,)
    5 (12345,)
    6 (123456,)

    由上面代码可以看出,在接收方角度,收数据前,先recv(4),交给struck解包,接下来我再接收这个解包后数字的字节数就好了..

    这就是解决粘包问题的核心思想..下面是struck的对照表

    我们已经会用struck解决粘包问题了..但是又出现一个新问题.struck不能转换无限长的数字.如果大文件就很难办了

    1 import struct
    2 s = struct.pack("i", 1234111111111111111111111111111111111111111)
    3 print(s, len(s))
    4 
    5 
    6 结果:
    7 s = struct.pack("i", 1234111111111111111111111111111111111111111)
    8 struct.error: argument out of range

    所以,又有另外一种更高级的解决办法.就是将这个无限大的数字..封装到我的字典,列表等容器中,并用json.dumps()将字典列表转换成字节码,

    再将这个字节码len()一下长度,用struck转换就容易多了..

    1 import json
    2 import struct
    3 n = [1234111111111111111111111111111111111111111]    # 不仅仅是列表,可以是字典,里面存储一些文件的名字,大小,md5等等数据.以便接收方使用
    4 j = json.dumps(n).encode()
    5 s = struct.pack("i", len(j))
    6 print(s, len(s))
    7 
    8 结果:
    9 b'-x00x00x00' 4

    这样子,我就是在数据的头部,先发送四个字节的struck,再发送json转换后的字节,最后在发送数据..

    1 接收方先收四个字节,知道了这个json转换后的字节长度,

    2 再读取这个长度的字节数,就能得到json转换后的字节数据,

    3 再用loads转成对象..或者一个字典或列表等,,然后里面的值,我就可以随便应用了,

    4 根据里面记录的数据的字节数,接收所有数据即可..

     1 # 接收和发送文件时,控制接收数就可以解决粘包了..控制接收数(循环)可参考下面代码的while判断语句..
     2 def recv_file(file_path):        
     3     recv_size = 0
     4     file_size = os.path.getsize(file_path)
     5     with open(file_path,"ab") as f:
     6         while recv_size<file_size:
     7             recv_data = client.recv(1024)
     8             recv_size += len(recv_data)
     9             f.write(recv_size)
    10 
    11 
    12 def send_file(file_path):
    13     send_size = 0
    14     file_size = os.path.getsize(file_path)
    15     with open(file_path,"rb") as f:
    16         while send_size<file_size:
    17             read_data = f.read(1024)
    18             send_data = server.send(read_data)
    19             send_size += len(send_data)    

    到此,接收方粘包问题已经解决了..

  • 相关阅读:
    06HTML和CSS知识点总结(六)
    05HTML和CSS知识点总结(五)
    webpack警告解除(WARNING in configuration The 'mode' option has not been set)
    如何Altium Designer AD输出元件清单及按照不同数值分类
    M57962
    艾科 驱动电路分析
    矢量旋度的散度恒为零
    迟滞比较器
    与非门SR锁存器
    寄存器与锁存器的区别
  • 原文地址:https://www.cnblogs.com/NoteBook3013/p/10426268.html
Copyright © 2020-2023  润新知