Socket接收大數據
上一篇博客中的簡單ssh實例,就是說當服務器發送至客戶端的數據,大於客戶端設置的數據,則就會把數據服務端發過來的數據剩余數據存在IO緩沖區中,這樣就會造成我們想要獲取數據的完整性。
解決思路:
1、改大客戶端接收的數據的大小,因為官方建議最多只能接收8k的數據,那服務端發送過來的數據很容易就會大於8K,這個思路並不能從根本上解決問題(不建議使用)
2、客戶端可以多收幾次,服務端給客戶端發數據之前,先計算一下要發給客戶端數據大小(len()判斷文件長度) ,比如說要發給客戶端數據是5k大小,先把5K這個值發送給客戶端,客戶端知道總共會接收5K的值,就知道需要接收多少次了,循環接收,直到5k數據全部接收完畢為止。
思路2邏輯流程圖:

服務端代碼:
import socket,os
server = socket.socket()
server.bind(("localhost",9999))
server.listen(5)
while True:
conn,addr = server.accept()
print("new addr:",addr)
while True:
data = conn.recv(1024)
if not data:
print("客戶端已斷開")
break
print("執行指令:",data)
cmd_res = os.popen(data.decode()).read()
print("before send:",len(cmd_res))
if len(cmd_res) == 0:
cmd_res = "cmd has no output...."
conn.send( str(len(cmd_res.encode())).encode() ) #發送服務端發送給客戶端數據的長度
conn.send(cmd_res.encode("utf-8")) #發送服務端的數據
print("send done")
server.close()
客戶端代碼:
import socket
client = socket.socket()
client.connect(("localhost",9999))
while True:
cmd = input(">>>:").strip()
if len(cmd) == 0:continue
client.send(cmd.encode("utf-8"))
cmd_res_size = client.recv(1024) #接收命令的長度
print("命令結果大小:",cmd_res_size.decode())
recevied_size = 0 #接收客戶端發來數據的計算器
recevied_data = b'' #客戶端每次發來內容的計數器
while recevied_size < int(cmd_res_size.decode()): #當接收的數據大小 小於 客戶端發來的數據
cmd_res = client.recv(1024)
recevied_size += len(cmd_res) #每次收到的服務端的數據有可能小於1024,所以必須用len判斷
recevied_data += cmd_res
else:
print(recevied_data.decode("utf-8","ignore"))
print("cmd res receive done ....",recevied_size)
client.close()
通過思路2寫出的代碼就能解決上一篇博客簡單ssh實例中數據展示不完整的問題,效果圖:


中文字符的坑:
通過上面代碼實驗后會發現客戶端准備接收數據的大小會和實際數據大小不一樣,實際數據要比客戶端接收的數據要大,如圖:

這是因為python用計算中文字符,按字符和字節算的話,長度的值是不一樣的,一個 中文字符=3個字節, 如圖 :

