python 用struct模組解決黏包問題
阿新 • • 發佈:2020-11-10
為什麼會出現黏包現象:
首先只有在TCP協議中才會出現黏包現象,是因為TCP協議是面向流的協議,在傳送的資料傳輸的過程中還有快取機制來避免資料丟失,因此,在連續傳送小資料的時候,以及接收大小不符的時候容易出現黏包現象。本質還是因為我們在接收資料的時候不知道傳送的資料的長短。
解決黏包問題
在傳輸大量資料之前首先告訴接收端要傳送的資料大小,如果想更漂亮的解決問題,可以通過struct模組來定製協議。
struct模組:
功能:可以把一個型別,如數字,轉成固定長度的bytes。
import struct ret = struct.pack('i',456872783) #'i'代表int,就是即將要把一共數字轉換成固定長度(4個位元組)的bystes型別 print(ret) num = struct.unpack('i',ret) #轉換回來,返回一個元組 print(num[0]) #提前元組中的值得到4096
解決黏包問題:
服務端:
import struct import socket sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr = sk.accept() while True: cmd = input('>>>') if cmd == 'q': #當輸入‘q'時,結束,並向客戶端傳送一個'q'。 conn.send(b'q') break conn.send(cmd.encode('gbk')) #將輸入的cmd命令傳送給客戶端 num = conn.recv(4) #接收位元組資訊(返回的訊息長度資訊)。 num = struct.unpack('i',num)[0] #將接收的位元組碼轉化為原來的型別並放在一個元組裡面,後面加[0]是提前出元組中的值。 res = conn.recv(int(num)).decode('gbk') #接收長度為num 的訊息。 print(res) #列印 conn.close() sk.close()
客戶端:
import struct import socket import subprocess sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: cmd = sk.recv(1024).decode('gbk') #接收服務端傳送來的cmd命令 if cmd == 'q': #當接收到‘q'時,結束。 break # 在客戶端執行接收到的cmd命令。並將正確的訊息和錯誤的訊息分別放入stdout和stderr管道。 res = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) std_out = res.stdout.read() #讀取管道內正確的訊息 std_err = res.stderr.read() #讀取管道內錯誤的訊息 len_num = len(std_out)+len(std_err) #計算正確和錯誤訊息的總長度 num_by = struct.pack('i',len_num) #將訊息總長度轉換成長度為4的位元組碼 sk.send(num_by) #傳送訊息長度資訊 sk.send(std_out) #傳送正確訊息 sk.send(std_err) #傳送錯誤訊息 sk.close()
以上就是python 用struct模組解決黏包問題的詳細內容,更多關於python struct模組的資料請關注我們其它相關文章!