day29-struct模塊解決黏包問題

#struct模塊能夠把一個數據類型,例如數字int,轉化成固定長度(4個字節)的bytes。int轉爲4個bytes。
#在大量傳輸數據以前先告訴接收端即將接收數據的大小,方可解決黏包問題:
#利用struct模塊打包要發送的數據的長度,接收端接收這個包,解包以後,接收這個長度的數據。
import struct
pack = struct.pack('i',4096) #打包,'i'表明int,把數字轉化成固定長度(4個字節)的bytes。
print(pack)                     #b'\x00\x10\x00\x00',4個字節(bytes)
unpack = struct.unpack('i',pack)#解包
print(unpack)                     #(4096,) 解包的結果是一個元祖
print(unpack[0])                  #4096,元祖的第一個元素就是字節數

#server:
import socket
import struct
sk = socket.socket()
sk.bind(('127.0.0.1',8888))
sk.listen()
conn,addr = sk.accept()
while True:
    cmd = input('>>>')
    if cmd == 'q':
        conn.send(b'q')
        break
    conn.send(cmd.encode('gbk'))     #encode編碼,把str轉化爲bytes。
    pack = conn.recv(4)       #接收的是client的包,由4個字節組成,這裏不須要decode解碼,由於下面是解包。
    unpack = struct.unpack('i',pack)
    ret = conn.recv(unpack[0]).decode('gbk')
    print(ret)

conn.close()
sk.close()

#client:
import socket
import subprocess
import struct
sk = socket.socket()
sk.connect(('127.0.0.1',8888))
while True:
    cmd = sk.recv(1024).decode('gbk')
    if cmd == 'q':
        break
    ret = subprocess.Popen(cmd,shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    std_out = ret.stdout.read() #讀取出來的內容是 bytes
    std_err = ret.stderr.read() #讀取出來的內容是 bytes
    len_num = len(std_out) + len(std_err) #計算出兩個輸出的長度
    pack = struct.pack('i',len_num)        #打包長度,pack由4個字節組成
    sk.send(pack) #server的pack = conn.recv(4)接收這個pack。
    sk.send(std_out)
    sk.send(std_err)

sk.close()
相關文章
相關標籤/搜索