python socket 連續send,出現粘包問題


使用網上socket代碼實現ssh功能,如下:

server.py
#服務端Linux系統下:處理命令並返回
import socket
import os
#聲明類型,生成socket鏈接對象
server = socket.socket()
#監聽接收端口元組(本地,端口),綁定要監聽的端口
server.bind(('localhost',6969))
#最大監聽數,允許多少人在排隊
server.listen(5)
while True: #循環鎖定訪問客戶端
print("等待執行指令")
conn,addr = server.accept() #返回鏈接的標記位conn,與連接的地址
print(conn, addr) #客戶端同過conn,addr進行通話,conn就是客戶端連接過來而在服務器端為其生成的一個連接實例
while True: #循環處理客戶端請求
print(conn)
data = conn.recv(1024) #1.接收數據,默認1024字節,緩沖區每次最多發32768,每個系統不同,超出數值會有限制。字節如果發不完會存在緩沖去,下次在發送
print('輸入命令為:',data.decode('utf-8'))
#Linux系統內可以判斷是否為空。
if not data:
print('斷開鏈接')
break
#執行命令,賦值給變量
res = os.popen(data.decode('utf-8')).read()
print('服務段執行命令后得到數據的size:',len(res))
if len(res)==0:
res='輸入命令有誤,請重新輸入'
# 返回res的總長度
conn.send(str(len(res)).encode('utf-8')) #len(str)為整數,需要變成字符格式才能使用encode方法
#返回res詳細結果
conn.send(res.encode('utf-8'))
#sendll就是循環send,用法發送大型文件。
#conn.sendll(res)
continue
#關閉鏈接
server.close()

client.py

#客戶端Linux系統下:輸入命令通過服務端返回
import socket

#聲明協議類型,同事生成socket連接對象
client = socket.socket()

#鏈接地址和端口,元組(本地,端口)
client.connect(('localhost',6969))

#使用input循環向服務端發送請求
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:
continue

#發送數據 b將字符串轉為bys類型
client.send(cmd.encode("utf-8")) #send只能發送bytes格式數據
#接收服務器端的返回(長度和詳細內容),需要聲明收多少,默認1024字節
cmd_res_size = client.recv(1024)
print(type(int(cmd_res_size.decode('utf-8'))))
print('客戶端收到執行后的命令長度:',cmd_res_size.decode('utf-8'))
received_size =0
received_data = b''
while received_size < int(cmd_res_size.decode('utf-8')):
cmd_res = client.recv(1024)
received_size += len(cmd_res)
received_data += cmd_res
else:
print('接收完成')

#打印data是recv的data
#print("recv_len:",cmd_res_len.decode('utf-8'))
print("recv:",received_data.decode('utf-8'))

#關閉接口
client.close()


上述代碼主要功能實現client端輸入Linux命令,傳送到server端執行並將命令執行結果返回client端,但有時候因為server.py中
# 返回res的總長度
conn.send(str(len(res)).encode('utf-8')) #len(str)為整數,需要變成字符格式才能使用encode方法
#返回res詳細結果
conn.send(res.encode('utf-8'))

連續發送數據,出現粘包,導致在client.py 中處理
cmd_res_size = client.recv(1024)
print(type(int(cmd_res_size.decode('utf-8'))))

取到cmd_res_size不為整數,導致int(cmd_res_size.decode('utf-8'))語句報錯


修改socket粘包問題方法如下:

1、添加time.sleep(0.2)
# 返回res的總長度
conn.send(str(len(res)).encode('utf-8')) #len(str)為整數,需要變成字符格式才能使用encode方法
time.sleep(0.2)
#返回res詳細結果
conn.send(res.encode('utf-8'))


2、在server和client之間添加個一個交互

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM