python 套接字 struck_Python socket粘包問題(最終解決辦法)

套接字:

就是將傳輸層以下的協議封裝成子接口

對于應用程序來說只需調用套接字的接口,寫出的程序自然是遵循tcp或udp協議的

實現第一個功能個:

實現:通過客戶端向服務端發送命令,調取windows下面的cmd窗口,將服務端執行命令的結構,返回并顯示在

客戶端窗口上。

subprocess:

1.可以將執行結果返回

2.返回值是bytes類型

(基于這兩點,可以應用在server端,將服務端的返回直接以bytes的格式直接send給客戶端,

實現在客戶端的顯示)

問題1:粘包問題

粘包問題:實際是由TCP協議在傳輸數據時的2大特性來的

TCP協議又叫流式協議,在數據傳輸上,只要客戶端發送相應的數據請求,

服務端會將數據像流水一樣不斷的send給客戶端

基于這個特點,就會存在一個問題,當客戶端給服務端發送一條命令,服務端成功接收并將命令的

結果返回到客戶端的時候,由于客戶端recv()的數量限制,可以一次不能完全取出,

這個時候就會存在,下次輸入命令客戶端首先拿到的返回值就是上次殘留的沒有收完的數據

基于粘包問題的解決思路就是:

發數據之前先把報頭發給對方,讓對方先知道要收的報頭的長度,后面再傳數據文件

自定義報頭:

為甚么要自定義報頭:

因為struck path(‘i’,3443242)

1.’i‘:類型不同,后面數字的長度大小也不同,大小是有限的(當超出范圍時會報錯)

2.因為報頭里面含有的內容可能不僅僅只有total_siz還有filename、hash等等,知識單純的把total_size

當做報頭傳入不合理,所以我們要自定義報頭

Server端配置

from socket import *

importsocket,subprocess,struct,json

server=socket.socket(AF_INET, SOCK_STREAM)

server.bind(('127.0.0.1', 8080))

server.listen(5)whileTrue:

conn,client=server.accept()print(client)whileTrue:try:

cmd= conn.recv(1024)if len(cmd) == 0: breakobj=subprocess.Popen(

cmd.decode('utf-8'),

shell=True,

stdout=subprocess.PIPE,

stderr=subprocess.PIPE,

)

out=obj.stdout.read()

err=obj.stderr.read()#制作報頭

header_dic={'filename':'a.txt','total_size':len(out)+len(err),'hash':'abc32i5o24'}#對包頭進行序列化

header_json=json.dumps(header_dic) #字符串格式

header_bytes=header_json.encode('utf-8')#1.先發型報頭的長度 len(header_bytes) struck為固定的4個字節

conn.send(struct.pack('i',len(header_bytes)))#2.發送報頭

conn.send(header_bytes)#3.發送真是數據

conn.send(out)

conn.send(err)exceptConnectionResetError:breakconn.close()

server.close()

Client端配置

from socket import *

importsocket,struct,json

client=socket.socket(AF_INET,SOCK_STREAM)

client.connect(('127.0.0.1',8080))whileTrue:

cmd=input('輸入你要操作的命令:')

client.send(cmd.encode('utf-8'))if len(cmd) == 0:continue

#1.先收報頭的四個字節,首先拿到報頭傳來的長度-》bytes

header=client.recv(4) #i類型足夠了 header為bytes類型

header_size=struct.unpack('i',header)[0] #拿到元祖形式,取第一個就是整個報頭的長度   print(header_size) ?#為報頭的長度值

#2.再收報頭(對應服務端的conn.send(header_bytes))

header_bytes=client.recv(header_size) #根據報頭的固定長度去收接收

#3.解析包頭(就是將header_bytes文件先解碼成json格式)

header_str=header_bytes.decode('utf-8')

header_dic=json.loads(header_str)print(header_dic)

total_size=header_dic['total_size']print(total_size)

recv_size=0 #定義一個初始的接收變量為0,只是個計數變量,為了統計與總的total_size的len大小

res=b''

while recv_size

recv_data=client.recv(1024) #每次傳過來的recv_data是bytes類型

res+=recv_data

recv_size+=len(recv_data) #循環增加每次接收值的長度#cmd=client.recv(1024)

print(res.decode('gbk'))

client.close()

粘包問題的最終解決方案,分析:

服務端:

目的為了自定義報頭(報頭中不僅包含長度,可能還有文件名等信息)

subprocess

...1.制作報頭(字典形式)

header_dic={'filename':'a.txt','total_size':len(out)+len(err),'hash':'abc32i5o24'}2.通過json將報頭序列化再encode為bytes類型

header_json=json.dumps(header_dic) #字符串類型

header_bytes=header_json.encode('utf-8') #bytes類型

3.發送報頭的長度,struck目的是固定封裝好的報頭為4個字節長度 =====對應客戶端剛開始 header=client.recv(4)

struck:1.將數字轉為bytes類型,保證發送過去的是bytes類型 2.固定4個字節

第一次發:conn.send(struck.pack('i',len(header_bytes)))

先傳給客戶端固定了收的時候報頭的長度,不至于報頭和其他內容粘在一起4.發送報頭 =======對應客戶端接收報頭 header_bytes=client.recv(header_size)

第二次發:conn.send(header_bytes)5.發送真實的數據

conn.send(out)

conn.send(err)

客戶端:(bytes--int)1.通過服務端返回的字節,拿到報頭的的長度

header=client.recv(4) #header是4個bytes字節

header_size=struck.unpack('i',header)[0] #字節頭-拿到int大小

2.再收報頭

header_bytes=client.recv(header_size) #bytes類型

3.解析報頭(1.先把內存中存放的bytes類型,用decode('utf-8')解碼為字符串)

header_json=header_bytes.decode('utf-8')

header_dic=json.loads(header_json) #json反序列化出字典格式 (對應server第2步)

print(header_dic)4.拿到字典中的報頭大小

total_size=header_dic['total_size']print(total_size)

struck功能輔助理解:所以客戶端剛開始接收4 大小是足夠把報頭接收完的。

#struck工鞥理解:importstruct#將整型轉成bytes

res=struct.pack('i',1232435436)print(res,len(res)) #res:為bytes類型,還是固定長度4(一般情況已經可以包含很多)

#將bytes轉成整型

aa=struct.unpack('i',res)print(aa,aa[0],type(aa)) #

print(len(res)) #4 一般情況多數bytes 4個長度足夠了

"""結果

b'\xecxuI' 4

(1232435436,) 1232435436

4"""

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/529244.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529244.shtml
英文地址,請注明出處:http://en.pswp.cn/news/529244.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python的lib文件夾_python遍歷文件夾os.path與pathlib

首先我們來一個需求,這個函數接受文件夾的名稱作為輸入參數,返回該文件夾中文件的路徑,以及其包含文件夾中文件的路徑。def print_dir_contents(sPath):import osfor sChild in os.listdir(sPath):sChildPath os.path.join(sPath,sChild)if …

python 數據字典用法_python數據字典的操作

一、什么是字典?字典是Python語言中唯一的映射類型。映射類型對象里哈希值(鍵,key)和指向的對象(值,value)是一對多的的關系,通常被認為是可變的哈希表。字典對象是可變的,它是一個容器類型,能存儲任意個數…

雙系統安裝deepin20_win10deepin15.10雙系統安裝教程

第二步:下載深度啟動盤制作工具深度啟動盤制作工具地址第三步:制作U盤啟動盤打開第二部下載的啟動盤制作工具,并準備一個u盤插入待裝系統的電腦,選擇鏡像文件后,下一步選擇磁盤并勾選格式化磁盤,點下一步開…

ubuntu19 安裝git_在Ubuntu 18.04上安裝Git

步驟1.首先,通過運行以下命令確保您的系統和apt包列表完全更新:apt-get update -yapt-get upgrade -y第2步。在Ubuntu 18.04上安裝Git。現在讓我們安裝git:apt install git您可以使用以下命令來檢查已安裝的git版本:$ git --versi…

mysql更新多條數據6_mysql語句:批量更新多條記錄的不同值

mysql更新語句很簡單,更新一條數據的某個字段,一般這樣寫:如果更新同一字段為同一個值,mysql也很簡單,修改下where即可:這里注意 ‘other_values’ 是一個逗號(,)分隔的字符串,如&am…

php mysql query 行數_如何在PHP中獲取MYSQL數據庫返回的數據的行數?

展開全部1. mysql_num_rows 可得到e69da5e887aa3231313335323631343130323136353331333337383861查詢記錄數<?php $con mysql_connect("localhost", "hello", "321");if (!$con){die(Could not connect: . mysql_error());}$db_selected …

mysql數據庫開發環境_MacOS下搭載開發環境之數據庫篇(Mysql + Navicat)

一、安裝Mysql1、官網下載mysql的tar包(提示&#xff1a;建議vpn環境下載)2、解壓并安裝tar包# 移動解壓后的二進制包到安裝目錄sudo mv mysql-5.7.19-osx10.9-x86_64 /usr/local/mysql# 更改 mysql 安裝目錄所屬用戶與用戶組cd /usr/localsudo chown -R root:wheel mysql# 初始…

mysql alter 唯一鍵_MySQL列屬性 之 唯一鍵

MySQL列屬性 之 唯一鍵唯一鍵唯一鍵&#xff1a;每張表往往有多個字段需要具有唯一性&#xff0c;數據不能重復&#xff0c;但是在每張表中&#xff0c;只能有一個主鍵&#xff0c;因此 唯一鍵就是用來解決表中多個字段需要具有唯一性的問題。例如身份證號碼應該每一行的記錄不…

如何在mysql中添加復選框_如何使用輸入和復選框更新mysql

如果我理解正確,您需要這樣做:mysql_query("UPDATE mp3SETaktif 1,baslik " . mysql_escape_string($_POST[baslik]) ."WHERE id $zuha");mysql_query("update mp3 set aktif 1,baslik $_POST[baslik]where id $_POST[id]")現在唯一的區別…

mysql 檢查列是否存在,如何檢查mysql表列是否存在?

How can I check if mysql table field even exists ?The column name is price and I need to see if it exists.Havent understood really how the EXISTS works...Any examples or ideas ?Thanks解決方案In PHP:$fields mysql_list_fields(database_name, table_name);$c…

mysql proxy yum_mysql 高可用架構 proxysql 之一 yum安裝

os:centos 7.4mysql: 5.7proxysql: 1.4.10ip 規劃如下&#xff1a;192.168.56.101 node1 (proxysql)192.168.56.102 node2 (mysql master)192.168.56.103 node3 (mysql slave)192.168.56.104 node4 (mysql slave)安裝mysql 5.7node2、node3、node4 安裝 mysql 5.7 software詳細…

wpf 使用位圖畫圖為什么斷斷續續_WPF的未來是微軟WinUi!

WPF(Windows Presentation Foundation)是微軟推出的基于Windows 的用戶界面框架&#xff0c;屬于.NET Framework 3.0的一部分。它提供了統一的編程模型、語言和框架&#xff0c;真正做到了分離界面設計人員與開發人員的工作&#xff1b;同時它提供了全新的多媒體交互用戶圖形界…

antd新增一行頁碼不正確_antd-Table@4.x對rowKey屬性的重構

時間&#xff1a;2020/04/26 &#xff0c;轉載請注明出處。寫在前面antd團隊于2020年2月發布了醞釀已久的antd4.0版本&#xff0c;對樣式的調整、部分組件邏輯的重構都進行了較大改動&#xff0c;本文針對Table的rowKey屬性重構作分析。由一個mistake帶來的思考在數據治理模塊的…

qt調用mysql調用了存儲過_Qt調用Server SQL中的存儲過程

Server SQL中的存儲過程如下&#xff1a;CREATE procedure PINSERTPCpcnum int,pcname varchar(50),pctype int,ipaddress varchar(50),port int,pcid int outputas--declare pcid intif exists (select * from COMPUTERTABLE where PcNum pcnum)set pcid -1elsebegininser…

pandas mysql index_Pandas從入門到精通(3)- Pandas多級索引MultiIndex

首先了解一下什么是多級索引&#xff0c;以及它的作用&#xff0c;為什么要有這個玩意。多級索引也稱為層次化索引(hierarchical indexing)&#xff0c;是指數據在一個軸上(行或者列)擁有多個(兩個以上)索引級別。之所以引入多級索引&#xff0c;在于它可以使用戶能以低維度形式…

tensorflow 啟動多個session_Tensorflow源碼解析7 -- TensorFlow分布式運行時

1 概述TensorFlow架構設計精巧&#xff0c;在后端運行時這一層&#xff0c;除了提供本地運行時外&#xff0c;還提供了分布式運行時。通過分布式訓練&#xff0c;在多臺機器上并行執行&#xff0c;大大提高了訓練速度。前端用戶通過session.run()啟動系統執行時&#xff0c;tar…

shell swt 樣式_SWT之路:SWT圖像顯示

簡明現代魔法 -> Java編程語言 -> SWT之路&#xff1a;SWT圖像顯示SWT之路&#xff1a;SWT圖像顯示2009-10-03程序演示還是先用SWT Desiner創建界面程序。然后創建一個Display對象和Image對象&#xff0c;和一個GC對象。類org.eclipse.swt.graphics.GC是一個封裝了所有可…

swool tcp mysql_swoole/mysql(異步)

# 異步Swoole\Mysql**(要求Workerman版本>3.3.6)**## 注意:此組件由swoole底層提供&#xff0c;由C語言編寫&#xff0c;具有超高性能。## 安裝&#xff1a;安裝有swoole擴展即可## 示例&#xff1a;phprequire_once ../Autoloader.php;use Workerman\Worker;use \Swoole\My…

xamarin和mysql_Xamarin.Android 使用 SQLiteOpenHelper 進行數據庫操作

一、前言在手機中進行網絡連接不僅是耗時也是耗電的&#xff0c;而耗電卻是致命的。所以我們就需要數據庫幫助我們存儲離線數據&#xff0c;以便在用戶未使用網絡的情況下也可以能夠使用應用的部分功能&#xff0c;而在需要網絡連接的功能上采用提示方式&#xff0c;讓用戶決定…

python 絕對值誤差小于10-6_Python 被低估了的 10 個小技巧

hi&#xff0c;各位朋友們&#xff0c;小帥b回來啦&#xff0c;幾日不見&#xff0c;想我了么&#xff1f;今天給大家分享幾個我認為不錯的 Python 小技巧&#xff0c;有些可能被你低估了喲&#xff0c;get 起來&#xff01;那么接下來就是&#xff1a;學習 Python 的正確姿勢俗…