標籤:popen 步驟 size print sock obj 二次 error: 間隔
server端配置:
import socket,subprocess,structfrom socket import *server=socket(AF_INET,SOCK_STREAM)server.bind((‘127.0.0.1‘,8080))server.listen(5)while True: conn,client_addr=server.accept() while True: try: cmd=conn.recv(1024) if len(cmd) == 0:break obj=subprocess.Popen( cmd.decode(‘utf-8‘), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) out=obj.stdout.read() #bytes類型 err=obj.stderr.read() print(len(out+err)) # 解決粘包問題的步驟,先髮型資料的長度 total_size=len(out)+len(err) #資料類型,1.變為bytes類型 2.還是個固定長度 #1.製作固定長度的包頭 header=struct.pack(‘i‘,total_size) #2.發送前序 conn.send(header) #固定資料報的head頭的大小(自訂資料) #下面是發送真是的資料 # conn.send(out+err) #2個包是一起發過去的,因為間隔短 conn.send(out) conn.send(err) #發過去的整體是一個資料報=前序+資料部分 except ConnectionResetError: break conn.close()server.close()
client端配置:
import socketimport socket,structclient=socket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect((‘127.0.0.1‘,8080))while True: cmd=input(‘輸入執行的命令:‘) if len(cmd) == 0: continue client.send(cmd.encode(‘utf-8‘)) #1.先收固定長度的的包頭預設stuck就是固定了長度為4 header=client.recv(4) #第二次再收不是下一個包頭,是上次命令的殘留 #2.解析包頭 total_size=struct.unpack(‘i‘,header)[0] #拿到的是個元祖,元祖的0就是這個長度值 print(total_size) #3.根據包頭內的資訊,收取真實資料 # client.recv(total_size) 因為現實資料量太大的時候就不行,所以考慮while迴圈 #思考如果資料大,total_size資料會特別大就會直接報錯 #為瞭解決輸入較大程式,定義一個小的變數,迴圈一點點就去收 recv_size=0 res=b‘‘ while recv_size < total_size: recv_data=client.recv(1024) #recv_data是bytes類型,是唯一真實的值,有多少就會收多少 res+=recv_data recv_size+=len(recv_data) print(res.decode(‘gbk‘))client.close()
Python socket粘包問題