python 解决粘包现象(struct模块)
Posted 唯你如我心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 解决粘包现象(struct模块)相关的知识,希望对你有一定的参考价值。
一. struct模块
该模块可以把一个类型,转换为固定长度的bytes
import struct lst = [1,2,4,3,5,] lst1 = [1,2,4,3,5,7,8,9,] a = struct.pack(\'i\',len(lst))#将列表的长度转化为固定的4字节 b = struct.pack(\'i\',len(lst1)) print(a,len(a)) print(b,len(b))
还可以将想要让服务端/客户端知道的信息做成字典,将字典的长度和字典打包发送 :
符号对应的类型以及转换之后的长度表 :
struct模块实现大文件传输 :
#server端 import socket import struct import json import os sk = socket.socket() sk.bind((\'127.0.0.1\',8989)) sk.listen() conn,addr = sk.accept() len_dic = struct.unpack(\'i\',conn.recv(4))[0]#unpack解包接受的是元组类型,索引为0是字典的长度 str_dic = conn.recv(len_dic).decode(\'utf-8\')#根据字典的长度将字典接收为字符串类型 dic = json.loads(str_dic)#将字符串类型的字典转换为字典(dict) if dic[\'opt\'] == \'upload\': up_load = \'D:\\a\\b\\c\\\\\' + os.path.basename(dic[\'filename\'])#路径拼接 # up_load = os.path.join(\'D:\\a\\b\\c\\\\\',os.path.basename(dic[\'filename\'])) while dic[\'filesize\'] >0: read_size = conn.recv(2048) with open(os.path.abspath(up_load),mode=\'ab\') as f1: f1.write(read_size) dic[\'filesize\'] -= len(read_size) if dic[\'opt\'] == \'download\': down_load = \'D:\\a\\b\\c\' conn.send(json.dumps(os.listdir(down_load)).encode(\'utf-8\')) while 1: s = conn.recv(2048).decode(\'utf-8\') file = os.path.abspath(down_load+\'/\'+s) print(file) if os.path.isdir(file): dic1 = {\'tybe\':\'dir\'} len_dic1 = struct.pack(\'i\',len(json.dumps(dic1))) conn.send(len_dic1 + json.dumps(dic1).encode(\'utf-8\')) conn.send(json.dumps(os.listdir(file)).encode(\'utf-8\')) down_load = os.path.abspath(file) continue elif os.path.isfile(file): dic2 = {\'tybe\':\'fil\',\'down_size\':os.path.getsize(file)} len_dic2 = struct.pack(\'i\',len(json.dumps(dic2))) conn.send(len_dic2 + json.dumps(dic2).encode(\'utf-8\')) with open(file,mode=\'rb\') as f: down_size = os.path.getsize(file) while down_size: a = f.read(2048) print(a)########### conn.send(a) down_size -= len(a) break
#client端 import socket import struct import os import json sk = socket.socket() sk.connect((\'127.0.0.1\',8989)) def upload(): dic = {\'opt\':\'upload\',\'filename\':None,\'filesize\':None} file = input(\'请输入一个想要上传的绝对路径: \') dic[\'filename\'] = file dic[\'filesize\'] = os.path.getsize(file) str_dic = json.dumps(dic) len_dic = struct.pack(\'i\',len(str_dic))#自动将字典的长度转换为4个bytes类型的长度 sk.send(len_dic + str_dic.encode(\'utf-8\')) with open(dic[\'filename\'],mode=\'rb\') as f: while dic[\'filesize\'] > 0: read_size = f.read(2048) sk.send(read_size) dic[\'filesize\'] -= len(read_size) def download(): dic = {\'opt\':\'download\',\'filename\':None,\'filesize\':None} sk.send(struct.pack(\'i\',len(json.dumps(dic)))+json.dumps(dic).encode(\'utf-8\')) while 1: lst = json.loads(sk.recv(2048).decode(\'utf-8\')) for k, v in enumerate(lst, 1): print(k, v) file = input(\'请根据序号输入想要下载的文件: \') sk.send(lst[int(file) - 1].encode(\'utf-8\')) len_dic = struct.unpack(\'i\',sk.recv(4))[0] str_dic = sk.recv(len_dic).decode(\'utf-8\') if json.loads(str_dic)[\'tybe\'] == \'dir\': continue elif json.loads(str_dic)[\'tybe\'] == \'fil\': down_file = \'D:\\a\\b\\c\\\\\'+lst[int(file) - 1] while json.loads(str_dic)[\'down_size\']: with open(down_file,mode=\'ab\') as f: down_ = sk.recv(2048) f.write(down_) json.loads(str_dic)[\'down_size\'] -= len(down_) if __name__ ==\'__main__\': lst = [\'上传\', \'下载\'] def mai(): for k,v in enumerate(lst,1): print(k,v) c = input(\'请按序号输入操作: \') if c == \'1\': upload() if c == \'2\': download() else: print(\'输入错误!\') mai()
以上是关于python 解决粘包现象(struct模块)的主要内容,如果未能解决你的问题,请参考以下文章