TCP传输时为避免粘包-根据协议传输-构建发送与接收携带信息的字典
特别注意:
1、这两个函数中的默认参数pro很重要:
(1)默认情况下“按照协议传输”:就是说,一定会传输“未知大小并且比较大的数据(大文件、携带一长串信息的字符串等)”,为了避免粘包,所以我们需要在发送这个数据之前传给接收方我们这个数据的具体信息(转换成bytes的大小、名字等等),所以会用struct模块将这个信息字典(转为byte类型)发送给接收方,接收方收到后再把这个数据拆成字典,找到接下来需要发送大文件的信息,制定接收规则,根据协议接收。
(2)否则,我们在发送或者接收的时候人为的将这个值设置为False的话,意思就是本次只传输一个字典,而且这个字典不会太大(我在接收端用1024接收的,当然也可以再设置的大点)。也就是说,我这次只传送一个字典,接下来不传送大数据了,因此我直接传送与接收字典就OK了!
2、注意,这里的“信息”我是用字典存的,因此发送端的参数是一个字典,接收端会收到一个字典!
3、注意:发送端与接收端的规则必须一致!也就是说发送端设置了根据协议发送了,接收端也必须根据协议接收!反之亦然!!
# -*- coding:utf-8 -*- import json import struct def pro_send(sk,dic,pro=True): str_dic = json.dumps(dic) bytes_dic = str_dic.encode('utf-8') # 默认选择协议发送 if pro: num_dic = struct.pack('i',len(bytes_dic)) sk.sendall(num_dic) sk.sendall(bytes_dic) def pro_recv(sk,pro=True): # 依据协议先收到的是字典的长度 if pro: num_dic = sk.recv(4) # 注意unpack得到的是一个元组,需要加上0索引取值 num = struct.unpack('i',num_dic)[0] str_dic = sk.recv(num).decode('utf-8') dic = json.loads(str_dic) # 不根据协议接收直接用1024大小的长度来接收 else: dic = json.loads(sk.recv(1024).decode('utf-8')) return dic