1. 程式人生 > >python 解決粘包現象(struct模塊)

python 解決粘包現象(struct模塊)

conn bin str 元組 dumps .get struct 下載 pytho

一. 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模塊)