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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本

發布時間:2023/12/10 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

立即學習:https://edu.csdn.net/course/play/24458/296243?utm_source=blogtoedu

粘包現象的解決:簡單版

?

1.思路:

????? 在服務器端計算出執行命令后結果的字節長度,然后再將字節數長度send即通知給客戶端,客戶端根據這個字節數的長度一次性即可將相應的命令執行結果給接收,進而解決了粘包問題。

?

2.知識點:

?

1)互聯網協議:報頭+數據

?

2)報頭是固定長度字節的,一般是4字節數,包含了一段數據的相關信息,如數據的字節總數以及相關描述等;

?

3)struct模塊,是python內置模塊,用于報頭的相關函數,如res = struct.pack('i',信息)是用于定制固定長度的函數,得到的是一個對象,而struct.unpack('i',res)則是解析報頭的函數,得到的是一個元組,第一個元素為字節數長度

?

3.關鍵代碼

''' 服務端 '''......#1接收客戶端發送過來的命令cmd = conn.recv(1024)#2處理命令,執行命令并且獲得命令得到的結果obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,#將正確運行命令得到的結果傳給管道stdout中stderr=subprocess.PIPE)#將沒有正確運行命令得到的返回信息存放在stderr管道中stdout = obj.stdout.read()stderr = obj.stderr.read()total_size = len(stderr + stdout)#1)定制固定長度的報頭,報頭包含命令執行結果的字節數長度header = struct.pack('i',total_size)#2)將報頭發送給客戶端conn.send(header)#3)將真實的命令執行結果信息發送給客戶端data = stdout + stderrconn.send(data)......''' 客戶端 '''.......#4、接收服務器返回來的數據recv()#1)先接收由服務器返回來的報頭,報頭是固定長度的,因此取前面4字節的數據即為報頭header = phone.recv(4)#返回的是一個對象#2)解析返回的報頭,獲得字節數總長信息obj_truple = struct.unpack('i',header)#返回的是一個元組total_size = obj_truple[0]#取元組第一個元素即為總字節數#3)接收真實的命令執行結果信息recv_size = 0data = b''while recv_size < total_size:recv_data = phone.recv(1024)#接收小于1024bytes的數據recv_size += len(recv_data)data += recv_dataprint('服務器返回來的數據:',data.decode('gbk')).......

結果:由結果可以得到,輸入相應的命令可以得到正確的命令執行結果

#第一個命令

請輸入:dir
服務器返回來的數據:? 驅動器 C 中的卷是 本地磁盤
?卷的序列號是 B476-3C7C

?C:\Users\jinlin\Desktop\python_further_study\socket編程\粘包現象解決(簡單版) 的目錄

2020/03/09? 14:46??? <DIR>????????? .
2020/03/09? 14:46??? <DIR>????????? ..
2020/03/09? 14:46???????????? 1,503 客戶端(粘包).py
2020/03/09? 14:45???????????? 1,434 服務器端(粘包).py
?????????????? 2 個文件????????? 2,937 字節
?????????????? 2 個目錄 122,025,189,376 可用字節

?

#第二個命令

請輸入:tasklist
服務器返回來的數據:
映像名稱?????????????????????? PID 會話名????????????? 會話#?????? 內存使用
========================= ======== ================ =========== ============
System Idle Process????????????? 0 Services?????????????????? 0????????? 4 K
System?????????????????????????? 4 Services?????????????????? 0??????? 568 K
smss.exe?????????????????????? 324 Services?????????????????? 0??????? 784 K
csrss.exe????????????????????? 524 Services?????????????????? 0????? 8,760 K
csrss.exe????????????????????? 620 Console??????????????????? 1???? 37,232 K
wininit.exe??????????????????? 628 Services?????????????????? 0????? 3,940 K
winlogon.exe?????????????????? 656 Console??????????????????? 1????? 6,564 K

..............

cmd.exe????????????????????? 11188 Console??????????????????? 1????? 2,304 K
tasklist.exe????????????????? 9056 Console??????????????????? 1????? 6,176 K

?

#第三個命令

請輸入:dir
服務器返回來的數據:? 驅動器 C 中的卷是 本地磁盤
?卷的序列號是 B476-3C7C

?C:\Users\jinlin\Desktop\python_further_study\socket編程\粘包現象解決(簡單版) 的目錄

2020/03/09? 14:46??? <DIR>????????? .
2020/03/09? 14:46??? <DIR>????????? ..
2020/03/09? 14:46???????????? 1,503 客戶端(粘包).py
2020/03/09? 14:45???????????? 1,434 服務器端(粘包).py
?????????????? 2 個文件????????? 2,937 字節
?????????????? 2 個目錄 122,024,615,936 可用字節

?

4.完整代碼

''' 服務端 ''' import socket import subprocess import struct phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',8080)) phone.listen(5) while True:#接收客戶端發送過來連接服務器請求res = phone.accept()conn,client_addr = reswhile True:try:#1接收客戶端發送過來的命令cmd = conn.recv(1024)#2處理命令,執行命令并且獲得命令得到的結果obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,#將正確運行命令得到的結果傳給管道stdout中stderr=subprocess.PIPE)#將沒有正確運行命令得到的返回信息存放在stderr管道中stdout = obj.stdout.read()stderr = obj.stderr.read()total_size = len(stderr + stdout)#1)定制固定長度的報頭,報頭包含命令執行結果的字節數長度header = struct.pack('i',total_size)#2)將報頭發送給客戶端conn.send(header)#3)將真實的命令執行結果信息發送給客戶端data = stdout + stderrconn.send(data)except ConnectionResetError:breakconn.close() phone.close() phone.close() ''' 客戶端 ''' #導入模塊 import socket import struct#1、設置phone套接字 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#2、連接服務器(打電話),本地地址:127.0.0.1 phone.connect(('127.0.0.1',8080))#3、向服務器發送請求send(),發送的數據不能直接發送字符串,因為要傳送到物理層底層,因此需要轉換成二進制的bytes類型進行發送,只需:發送的數據.encode('utf-8')即可 while True:cmd = input("請輸入:")#修復客戶端發送空字符串而服務器卡在接收信息處的bug,continue表示跳出本次循環,重新開始下一次的循環if not cmd:continuephone.send(cmd.encode('utf-8'))#4、接收服務器返回來的數據recv()#1)先接收由服務器返回來的報頭,報頭是固定長度的,因此取前面4字節的數據即為報頭header = phone.recv(4)#返回的是一個對象#2)解析返回的報頭,獲得字節數總長信息obj_truple = struct.unpack('i',header)#返回的是一個元組total_size = obj_truple[0]#取元組第一個元素即為總字節數#3)接收真實的命令執行結果信息recv_size = 0data = b''while recv_size < total_size:recv_data = phone.recv(1024)#接收小于1024bytes的數據recv_size += len(recv_data)data += recv_dataprint('服務器返回來的數據:',data.decode('gbk'))#5、關閉套接字phone phone.close()

?

?

總結

以上是生活随笔為你收集整理的学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本的全部內容,希望文章能夠幫你解決所遇到的問題。

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