粘包現象和解決方法
阿新 • • 發佈:2019-01-05
一.緩衝區
緩衝區:將程式和網路解耦(類似於cpu和硬碟需要記憶體來緩衝一樣)
輸入緩衝區
輸出緩衝區
二.subprocess和struct模組的簡單認識
import subprocess sub_obj = subprocess.Popen( "dir", # cmd指令 shell=True, stdout = subprocess.PIPE, #正確的指令存放位置 stderr = subprocess.PIPE # 錯誤的指令存放位置 )
print(sub_obj.stdout.read().decode("gbk")) # read 拿到的是位元組,需要解碼(需要解碼的位元組是系統預設的)
import struct a = 10 byt = struct.pack("i",a) # 將int型別的a打包成4個位元組長度的二進位制 a1 = struct.unpack("i",byt) # 將byt解包成一個int型別,返回的是一個元組
三.兩種粘包現象(TCP)
1.連續(傳送資料間隔短)兩個小的資料流會被優化演算法給組合到一起併發送,造成粘包
模擬粘包現象服務端
import socket server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() from_client_msg1 = conn.recv(1024) print(from_client_msg1) from_client_msg2 = conn.recv(1024) print(from_client_msg2)
模擬粘包現象客戶端
import socket client = socket.socket() client.connect(("127.0.0.1",8888)) to_send1 = client.send(b"123") to_send2 = client.send(b"123")
2.一個大的資料流過大,超過revc的值,那麼會一次接收不完,暫時存放在緩衝區,下次再接收的時候就會拿到一六的資料,造成粘包
模擬粘包現象服務端
import socket import subprocess server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024).decode("utf-8") # 一次只能接收1024b 剩下的存在緩衝區 第二次再接收會粘包 sub_obj = subprocess.Popen( from_client_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) to_client_res = sub_obj.stdout.read() print(len(to_client_res)) conn.send(to_client_res)
模擬粘包現象客戶端
import socket client = socket.socket() ip_port = ("127.0.0.1",8888) client.connect(ip_port) while 1: cmd = input("請輸入cmd指令:").encode("utf-8") # 輸入ipconfig -all client.send(cmd) server_cmd_res = client.recv(1024).decode("gbk") print(server_cmd_res)
四.產生粘包的原因及解決方案
1.產生粘包的原因:接收方不知道訊息之間的界限,不知道一次性提取多少資料造成的
2.解決粘包現象的方案:自定義一個長度報頭
解決粘包現象服務端
import socket import subprocess import struct server = socket.socket() ip_port = ("127.0.0.1",8888) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: from_client_cmd = conn.recv(1024).decode("utf-8") sub_obj = subprocess.Popen( from_client_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # print(sub_obj.stdout.read()) sub_res = sub_obj.stdout.read() cmd_len = len(sub_res) cmd_len_byt = struct.pack("i",cmd_len) conn.send(cmd_len_byt + sub_res)
解決粘包現象客戶端
import socket import struct client = socket.socket() client.connect(("127.0.0.1",8888)) while 1: cmd = input("請輸入cmd指令:").encode("utf-8") client.send(cmd) cmd_len_byt = client.recv(4) cmd_len = struct.unpack("i",cmd_len_byt)[0] cmd_msg = client.recv(cmd_len).decode("gbk") print(cmd_msg)