日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

解决socket粘包的两种low版模式 os.popen()和struct模块

發布時間:2025/4/16 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解决socket粘包的两种low版模式 os.popen()和struct模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

無注釋版

os.popen()模式

server端

import socket import osphone = socket.socket() phone.bind(("localhost",8088)) phone.listen()while 1:conn,addr = phone.accept()while 1:try:from_client_data = conn.recv(1024)if from_client_data.upper() == b'Q':print("客戶端退出")breakprint(from_client_data.decode('utf-8'))cmd_res = os.popen(from_client_data.decode("utf-8")).read()if len(cmd_res) == 0:cmd_res = "cmd hs no output..."print(len(cmd_res.encode('gbk')))conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk'))client.ack = conn.recv(1024)conn.send(cmd_res.encode('gbk'))except ConnectionResetError:breakconn.close() phone.close()

client端

import socket phone = socket.socket() phone.connect(('localhost',8088)) while 1:client_data = input(">>>")if not client_data:print("發送的內容不能為空")continuephone.send(client_data.encode("utf-8"))if client_data.upper() == "Q":quit()else:server_data = phone.recv(1024)phone.send("準備好接收了".encode('utf-8'))total_size = int(server_data.decode('gbk'))total_data = b''while 1:if len(total_data) < total_size:total_data += phone.recv(1024)print(len(total_data))else:breakprint(total_data.decode('gbk')) phone.close()

struct模塊解決粘包

server端

import socket import subprocess import structphone = socket.socket() phone.bind(("localhost",8088)) phone.listen(5)while 1:conn,addr = phone.accept()print(addr)while 1:try:from_client_data = conn.recv(1024)if from_client_data.upper() == b'Q':print("客戶端退出")breakprint(from_client_data.decode('utf-8'))obj = subprocess.Popen(from_client_data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)ret = obj.stdout.read()+obj.stderr.read()total_size = len(ret)header = struct.pack('i',total_size)print(total_size)conn.send(header)conn.send(ret)except ConnectionResetError:breakconn.close() phone.close()

client端

import socket import struct phone = socket.socket() phone.connect(('localhost',8088)) while 1:client_data = input(">>>")if not client_data:print("發送的內容不能為空")continuephone.send(client_data.encode("utf-8"))if client_data.upper() == "Q":quit()else:server_data = phone.recv(4)total_size = struct.unpack('i',server_data)[0]total_data = b''while 1:if len(total_data) < total_size:total_data += phone.recv(1024)print(len(total_data))else:breakprint(total_data.decode('gbk'))# print(int(server_data.decode('gbk'))) phone.close()

有注釋版

os.popen()模式

server端

import socket import osphone = socket.socket() # 實例化一個socket對象phone.bind(("localhost",8088)) # 綁定地址(host,port)到套接字,在AF_INET下,以元組(host,port)的形式表示地址phone.listen(5) # 開始TCP監聽。backlog指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少為1,大部分應用程序設為5就可以了。while 1: # 開啟循環,多個用戶同時連接(當然不是并發,排隊連接)conn,addr = phone.accept()# 被動接受TCP客戶端連接,(阻塞式)等待連接的到來,會有兩個值,conn我也不明白是什么值,addr是客戶端連接的地址while 1: # 客戶端與服務端多次對話,客戶端多次執行循環try: # 異常處理,客戶端直接退出ConnectionResetError錯誤from_client_data = conn.recv(1024) # 接收客戶端數據if from_client_data.upper() == b'Q': # 判斷客戶端輸入是否是q或Q,如果是q,直接退出當前連接print("客戶端退出")breakprint(from_client_data.decode('utf-8')) # 輸出客戶端轉碼后的數據cmd_res = os.popen(from_client_data.decode("utf-8")).read() # 執行os命令,通過popen執行cmd命令if len(cmd_res) == 0: # 如果沒有該命令,返回下面結果cmd_res = "cmd hs no output..."conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk')) # 發送數據,首先計算cmd_res的gbk字節長度,然后轉換成字符串發送給客戶端,因為int型不能發送print(len(cmd_res.encode('gbk'))) # 輸出該命令返回的長度conn.send(cmd_res.encode('gbk')) # 執行一個接收,截斷上下兩個的粘包conn.send(cmd_res.encode('gbk')) # 發送給客戶端except ConnectionResetError:breakconn.close() # 關閉連接 phone.close() # 關閉連接

client端

import socket phone = socket.socket() # 實例化對象 phone.connect(('localhost',8088)) # 主動初始化TCP服務器連接,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。 while 1: # 循環輸入client_data = input(">>>")if not client_data: # 如果輸入為空,not client_data 則為Trueprint("發送的內容不能為空")continuephone.send(client_data.encode("utf-8")) # 給服務端發送信息if client_data.upper() == "Q": # q退出quit()else:server_data = phone.recv(1024) # 接收返回的字節長度phone.send("準備好接收了".encode('utf-8')) # 給服務端發送消息,阻塞服務端上下造成粘包的問題(low版)total_size = int(server_data.decode('gbk')) # 接收到的是字符串,轉換成整型total_data = b'' # 剛開始設置為0,空字符串則為0,前面加b表示字節while 1: # 如果我收到的字節小于total_size,則一直循環if len(total_data) < total_size:total_data += phone.recv(1024) # 每次把信息加到total_data中print(len(total_data))else:breakprint(total_data.decode('gbk')) # 輸出返回的結果 phone.close() # 關閉連接

struct模塊解決粘包

server端

import socket import subprocess import structphone = socket.socket() # 實例化一個socket對象 phone.bind(("localhost",8088)) # 綁定地址(host,port)到套接字,在AF_INET下,以元組(host,port)的形式表示地址 phone.listen(5) # 開始TCP監聽。backlog指定在拒絕連接之前,操作系統可以掛起的最大連接數量。該值至少為1,大部分應用程序設為5就可以了。while 1:# 開啟循環,多個用戶同時連接(當然不是并發,排隊連接)conn,addr = phone.accept()# 被動接受TCP客戶端連接,(阻塞式)等待連接的到來,會有兩個值,conn我也不明白是什么值,addr是客戶端連接的地址print(addr)while 1: # 客戶端與服務端多次對話,客戶端多次執行循環try: # 異常處理,客戶端直接退出ConnectionResetError錯誤from_client_data = conn.recv(1024) # 接收客戶端數據if from_client_data.upper() == b'Q': # 判斷客戶端輸入是否是q或Q,如果是q,直接退出當前連接print("客戶端退出")breakprint(from_client_data.decode('utf-8')) # 輸出客戶端轉碼后的數據obj = subprocess.Popen(from_client_data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)# subprocess 模塊中的代碼# shell: 命令解釋器,相當于調用cmd 執行指定的命令。# stdout:正確結果丟到管道中。# stderr:錯了丟到另一個管道中。# windows操作系統的默認編碼是gbk編碼。ret = obj.stdout.read()+obj.stderr.read() # 加的是字節# 正確的輸出跟錯誤的輸出加起來,因為正確輸出時,錯誤輸出為空,所以加起來相當于0+1,沒什么區別total_size = len(ret) # 計算返回命令的長度header = struct.pack('i',total_size) # 將一個數字轉化成等長度的bytes類型。print(total_size) # 打印出返回命令的長度conn.send(header) # 發送固定長度的報頭conn.send(ret) # 給客戶端發送返回命令的結果except ConnectionResetError: breakconn.close() # 關閉連接 phone.close() # 關閉連接

client端

import socket import struct phone = socket.socket() # 實例化對象 phone.connect(('localhost',8088)) # 主動初始化TCP服務器連接,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。 while 1: # 循環輸入client_data = input(">>>")if not client_data: # 如果輸入為空,not client_data 則為Trueprint("發送的內容不能為空")continuephone.send(client_data.encode("utf-8")) # 給服務端發送信息if client_data.upper() == "Q": # q退出quit()else:server_data = phone.recv(4) # 接收報頭長度total_size = struct.unpack('i',server_data)[0] # 反解報頭total_data = b'' # 剛開始設置為0,空字符串則為0,前面加b表示字節while 1: # 如果我收到的字節小于total_size,則一直循環if len(total_data) < total_size: total_data += phone.recv(1024) # 每次把信息加到total_data中print(len(total_data))else:breakprint(total_data.decode('gbk')) # 輸出返回的結果,windows默認gbk# print(int(server_data.decode('gbk'))) phone.close() # 關閉連接

轉載于:https://www.cnblogs.com/alex3174/p/11360954.html

總結

以上是生活随笔為你收集整理的解决socket粘包的两种low版模式 os.popen()和struct模块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。