一、粘包問題
1、問題一:無法確認對方發送過來資料的大小,對資料接收有影響
server.py檔案內容:
""" 先啟動套接字服務端 注意: 客戶端一次發送,服務端先一次接收,再發送 """ import socket import subprocess server = socket.socket() server.bind(("127.0.0.1", 9527)) server.listen(5) while True: conn, addr = server.accept() print(addr) while True: try: # 從記憶體中獲取資料 data = https://www.cnblogs.com/jsxxd/archive/2020/11/02/conn.recv(1024) if len(data) == 0: continue data = data.decode("utf-8") if data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/= "q": break # 呼叫subprocess,對終端進行操作,并獲取操作后正確或錯誤的結果 # 接收轉碼后的字串 obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 將結果交給result變數 result = obj.stdout.read() + obj.stderr.read() print(result.decode("gbk")) # 將結果回傳給客戶端 conn.send(result) except Exception as e: print(e) break conn.close()
client.py檔案內容:
""" 啟動服務端后再啟動客戶端 """ import socket client = socket.socket() client.connect(("127.0.0.1", 9527)) while True: cmd = input("請輸入服務端命令:") client.send(cmd.encode("utf-8")) data = client.recv(1024) # 這里只接受到1024位元組資料,可以調整,但是對記憶體有影響 if len(data) == 0: continue if data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/= "q": break print(data.decode('gbk'))
server.py執行結果:

client.py執行結果:

2、問題二:在發送資料間隔短并且資料量小的情況下,會將所有資料一次性傳入
server.py檔案內容:
""" 先啟動套接字服務端 注意: 客戶端一次發送,服務端先一次接收,再發送 """ import socket server = socket.socket() server.bind(("127.0.0.1", 9527)) server.listen(5) conn, addr = server.accept() data = conn.recv(1024) print(data)
client.py檔案內容:
""" 啟動服務端后再啟動客戶端 """ import socket client = socket.socket() client.connect(("127.0.0.1", 9527))
'''
發送三次請求,理論上結果應該是
b"hello"
b"hello"
b"hello"
''' client.send(b"hello") client.send(b"hello") client.send(b"hello")
server.py執行結果:

3、解決粘包問題(struct模塊)
1、struct模塊是什么
struct模塊是一個python內置模塊,他可以將固定長度的資料,打包成固定格式的長度
" i "模式:可以將資料打包成 4 個bytes
2、struct模塊的作用
可以將真實資料,做成一個固定長度的報頭,客戶端發送給服務端,服務端可以接受報頭,然后對報頭進行解包,獲取真實資料的長度,進行接收即可
3、struct模塊的使用
import struct data = b'11111111111111' # 打包制作報頭 header = struct.pack("i", len(data)) print(header) # 解包獲取真實資料長度 ---> 得到一個元組,元組中第一個值是真實資料的長度 res = struct.unpack("i", header)[0] print(res)
執行結果:
b'\x0e\x00\x00\x00' 14
4、粘包問題解決方法
只要確認對方資料的大小(長度),根據大小進行接收即可解決
- 無論哪一端先發送資料(例 客戶端先行發送資料)
- 客戶端
- 先制作報頭并發送 struct.pack()
- 發送真實資料
- 服務端:
- 接收報頭,并解包獲取真實資料長度 struct.unpack()
- 根據真實資料長度 接收真實資料
server.py檔案內容:
import socket import subprocess import struct server = socket.socket() server.bind(("127.0.0.1", 8001)) server.listen(5) while True: conn, addr = server.accept() # print(addr) while True: try: # 獲取客戶端傳過來的報頭 client_headers = conn.recv(4) # 解包獲取真實資料長度 data_len = struct.unpack("i", client_headers)[0] # 準備接收真實資料 data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/ conn.recv(data_len) if len(data) == 0: continue data = data.decode("utf-8") if data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/= "q": break # 呼叫subprocess,對終端進行操作,并獲取操作后正確或錯誤的結果 # 接收轉碼后的字串 obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 將結果交給result變數 result = obj.stdout.read() + obj.stderr.read() # 服務端做一個報頭發送給客戶端 server_headers = struct.pack('i', len(result)) # 傳送報頭資料 conn.send(server_headers) # 待客戶端確認長度后,發送真實資料回傳給客戶端 conn.send(result) except Exception as e: print(e) break conn.close()
client.py檔案內容:
import socket import struct client = socket.socket() client.connect(("127.0.0.1", 8001)) while True: cmd = input("請輸入服務端命令:") cmd_bytes = cmd.encode("utf-8") # 做一個報頭 client_headers = struct.pack("i", len(cmd_bytes)) # 想服務端傳送報頭 client.send(client_headers) # 待服務端確認資料長度后,發送真實資料 client.send(cmd_bytes) # 獲取服務端的傳過來的報頭 server_headers = client.recv(4) # 解包獲取資料的真實長度 data_len = struct.unpack('i', server_headers)[0] # 準備接受真實資料 data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/ client.recv(data_len) if len(data) == 0: continue if data =https://www.cnblogs.com/jsxxd/archive/2020/11/02/= "q": break print(data.decode('gbk'))
可自行測驗,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/200866.html
標籤:其他
上一篇:粘包問題以及解決方法
下一篇:一線外包員工的生活成長
