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

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

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

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

所以就用到了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'\xd2\x04\x00\x00' 4
2 b'90\x00\x00' 4
3 b'@\xe2\x01\x00' 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'-\x00\x00\x00' 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)    

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

 

转载于:https://www.cnblogs.com/NoteBook3013/p/10426268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP协议是一种面向连接的可靠传输协议,它将数据分成一个一个的数据进行传输。但是,由于网络传输的不确定性,TCP和分问题就会出现。 1. TCP问题 TCP问题是指发送方将多个数据合并成一个数据发送,接收方无法区分多个数据的边界,从而无法正确处理数据。造成TCP问题的原因有多种,比如发送方发送的数据过大、发送速度过快、网络延迟等。 解决方法: (1) 设置消息边界标识符 在发送的消息中添加一个特殊的标识符,如换行符、空格等,用来标识消息的边界。接收方根据标识符来判断消息的边界,将消息分隔成多个数据。 (2) 定长消息 可以设置一个固定长度的消息,每次发送的数据都是定长的。这样接收方就可以根据固定长度来将消息分隔成多个数据。 2. TCP分问题 TCP分问题是指发送方将一个数据分成多个数据发送,接收方接收后需要将多个数据组合成一个完整的数据,才能进行处理。造成TCP分问题的原因有多种,比如发送方发送的数据过大、网络拥塞等。 解决方法: (1) 设置消息长度 在消息中添加消息长度信息,接收方接收到数据后,根据长度信息将多个数据组合成一个完整的数据。 (2) 固定长度消息 发送方每次发送的数据都是固定长度的,接收方根据固定长度来将多个数据组合成一个完整的数据。 总之,TCP和分问题可以通过合理的协议设计和网络优化来解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值