Python數(shù)據(jù)傳輸黏包問題
1.socket黏包問題原理
黏包:指數(shù)據(jù)與數(shù)據(jù)之間沒有明確的分界線,導(dǎo)致不能正確的讀取數(shù)據(jù)。
應(yīng)用數(shù)據(jù)想要發(fā)送數(shù)據(jù)就必須將數(shù)據(jù)交給操作系統(tǒng),而操作系統(tǒng)需要同時為所有的應(yīng)用程序提供數(shù)據(jù)傳輸服務(wù),就意味著不可能馬上將應(yīng)用數(shù)據(jù)發(fā)送,就需要為程序提供一個緩沖區(qū),用于臨時存放數(shù)據(jù)。
當(dāng)發(fā)送數(shù)據(jù)很快,有兩條數(shù)據(jù)都在緩沖區(qū)時,操作系統(tǒng)可能將兩個數(shù)據(jù)發(fā)給接收方,數(shù)據(jù)之間沒有分界線,接收方會誤認(rèn)為是一條數(shù)據(jù)。
2.UDP協(xié)議
UDP在收發(fā)數(shù)據(jù)時是基于數(shù)據(jù)包的,即一個包一個包的發(fā)送,包與包之間有明確的分界,到達(dá)對方緩沖區(qū)后也是獨(dú)立數(shù)據(jù)包。這種方式存在的問題:
①發(fā)送數(shù)據(jù)的長度每個操作系統(tǒng)會有不同的限制,數(shù)據(jù)超過限制則無法發(fā)送;
②接收方接收數(shù)據(jù)時,如果應(yīng)用程序提供的緩存容量小于數(shù)據(jù)包的長度,則會造成數(shù)據(jù)的丟失,而緩沖區(qū)大小不可能無限大。
這意味著UDP不會出現(xiàn)黏包問題,但會丟失數(shù)據(jù),不可靠。
3.TCP協(xié)議
TCP增加了一套校驗規(guī)則來保證數(shù)據(jù)的完整性,會將超過TCP包最大長度的數(shù)據(jù)拆分為多個TCP包,并在傳輸數(shù)據(jù)時為每一個TCP數(shù)據(jù)包指定一個順序號,接收方在收到TCP數(shù)據(jù)包后按照順序?qū)?shù)據(jù)包進(jìn)行重組,重組后的數(shù)據(jù)全都是二進(jìn)制數(shù)據(jù),且每次收到的二進(jìn)制數(shù)據(jù)之間沒有明顯的分界?;谶@種工作機(jī)制,TCP在三種情況下發(fā)生黏包問題:
①當(dāng)單個數(shù)據(jù)包較小時,接收方可能一次性讀取了多個包的數(shù)據(jù);
②當(dāng)整體數(shù)據(jù)較大時,接收方可能一次性僅讀取了一個包的一部分內(nèi)容;
③另外TCP協(xié)議為提高效率,增加了一種優(yōu)化機(jī)制,會將數(shù)據(jù)小且發(fā)送間隔短的數(shù)據(jù)合并發(fā)送,該機(jī)制也會導(dǎo)致發(fā)送方將兩個數(shù)據(jù)包粘在一起發(fā)送。
也就是說,TCP傳輸數(shù)據(jù)是可靠的,但是會黏包。
4.發(fā)送方出現(xiàn)的黏包
服務(wù)器端:
from socket import * server_socket = socket(AF_INET,SOCK_STREAM) server_socket.bind(('',8080)) server_socket.listen(5) ? new_socket,client_addr = server_socket.accept() ? data1 = new_socket.recv(1024) data2 = new_socket.recv(1024) print("收到的第一條數(shù)據(jù):",data1) print("收到的第二條數(shù)據(jù):",data2) ? new_socket.close() server_socket.close()
客戶端:
from socket import * ? client_socket = socket(AF_INET,SOCK_STREAM) client_socket.connect(('10.175.193.126',8080)) client_socket.send('hello'.encode('utf-8')) client_socket.send('word'.encode('utf-8')) client_socket.close()
服務(wù)器端接收到的數(shù)據(jù):
由于客戶端兩條數(shù)據(jù)發(fā)送間隔太短且數(shù)據(jù)包太小,被服務(wù)器端誤認(rèn)為是一條數(shù)據(jù)。
5. 接收方出現(xiàn)的黏包
服務(wù)器端:
from socket import * import time ? server_socket = socket(AF_INET,SOCK_STREAM) server_socket.bind(('',8080)) server_socket.listen(5) ? new_socket,client_addr = server_socket.accept() print("連接成功!",client_addr) ? data1 = new_socket.recv(3) #每次只接收三個字節(jié),接收不完整 time.sleep(6) print("收到的第一條數(shù)據(jù):",data1) ? data2 = new_socket.recv(10) #接收第一次未接收的數(shù)據(jù),若有空間,會繼續(xù)接收新數(shù)據(jù) print("收到的第二條數(shù)據(jù):",data2) ? new_socket.close() server_socket.close()
客戶端:
from socket import * #通過time模塊使客戶端發(fā)送多個數(shù)據(jù)包時,時間間隔變長 import time ? client_socket = socket(AF_INET,SOCK_STREAM) client_socket.connect(('10.175.193.126',8080)) client_socket.send('hello'.encode('utf-8')) time.sleep(5) #讓當(dāng)前線程休眠5秒 client_socket.send('word'.encode('utf-8')) ? client_socket.close()
服務(wù)器端接收到的數(shù)據(jù):
6.黏包的成因
①服務(wù)器端出現(xiàn)黏包:接收方不知道消息之間的界限,不知道一個消息要提取多少字節(jié)的數(shù)據(jù)造成的;
②客戶端出現(xiàn)黏包:TCP在發(fā)送數(shù)據(jù)少且間隔時間短的數(shù)據(jù)包時,會將幾條合并一起發(fā)送。
到此這篇關(guān)于Python數(shù)據(jù)傳輸黏包問題的文章就介紹到這了,更多相關(guān)Python數(shù)據(jù)傳輸黏包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- python使用socket高效傳輸視頻數(shù)據(jù)幀(連續(xù)發(fā)送圖片)
- python使用tcp傳輸圖片數(shù)據(jù)
- python 中Arduino串口傳輸數(shù)據(jù)到電腦并保存至excel表格
- 對python中基于tcp協(xié)議的通信(數(shù)據(jù)傳輸)實例講解
- 在python環(huán)境下運(yùn)用kafka對數(shù)據(jù)進(jìn)行實時傳輸?shù)姆椒?/a>
- 使用python實現(xiàn)http及ftp服務(wù)進(jìn)行數(shù)據(jù)傳輸?shù)姆椒?/a>
- Python爬蟲抓取手機(jī)APP的傳輸數(shù)據(jù)
- python網(wǎng)絡(luò)編程之?dāng)?shù)據(jù)傳輸U(kuò)DP實例分析
- python實現(xiàn)udp數(shù)據(jù)報傳輸?shù)姆椒?/a>
相關(guān)文章
解決pycharm中導(dǎo)入自己寫的.py函數(shù)出錯問題
今天小編就為大家分享一篇解決pycharm中導(dǎo)入自己寫的.py函數(shù)出錯問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02numpy array找出符合條件的數(shù)并賦值的示例代碼
本文主要介紹了numpy array找出符合條件的數(shù)并賦值的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05零基礎(chǔ)寫python爬蟲之爬蟲的定義及URL構(gòu)成
俗話說工欲善其事必先利其器,作為本系列文章的第一篇,我們同樣也需要先利其器,先把爬蟲的定義以及寫爬蟲所需要的基礎(chǔ)知識先介紹給大家。2014-11-11python 列表,數(shù)組,矩陣兩兩轉(zhuǎn)換tolist()的實例
下面小編就為大家分享一篇python 列表,數(shù)組,矩陣兩兩轉(zhuǎn)換tolist()的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04一文教你用python編寫Dijkstra算法進(jìn)行機(jī)器人路徑規(guī)劃
迪杰斯特拉(Dijkstra)算法是典型最短路徑算法,用于計算一個節(jié)點(diǎn)到其他節(jié)點(diǎn)的最短路徑,這篇文章主要給大家介紹了關(guān)于利用python編寫Dijkstra算法進(jìn)行機(jī)器人路徑規(guī)劃的相關(guān)資料,需要的朋友可以參考下2021-08-08