日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python數據傳輸黏包問題_python

作者:長得丑就要多讀書 ? 更新時間: 2022-06-12 編程語言

1.socket黏包問題原理

黏包:指數據與數據之間沒有明確的分界線,導致不能正確的讀取數據。

應用數據想要發送數據就必須將數據交給操作系統,而操作系統需要同時為所有的應用程序提供數據傳輸服務,就意味著不可能馬上將應用數據發送,就需要為程序提供一個緩沖區,用于臨時存放數據。

當發送數據很快,有兩條數據都在緩沖區時,操作系統可能將兩個數據發給接收方,數據之間沒有分界線,接收方會誤認為是一條數據。

2.UDP協議

UDP在收發數據時是基于數據包的,即一個包一個包的發送,包與包之間有明確的分界,到達對方緩沖區后也是獨立數據包。這種方式存在的問題:

①發送數據的長度每個操作系統會有不同的限制,數據超過限制則無法發送;

②接收方接收數據時,如果應用程序提供的緩存容量小于數據包的長度,則會造成數據的丟失,而緩沖區大小不可能無限大。

這意味著UDP不會出現黏包問題,但會丟失數據,不可靠。

3.TCP協議

TCP增加了一套校驗規則來保證數據的完整性,會將超過TCP包最大長度的數據拆分為多個TCP包,并在傳輸數據時為每一個TCP數據包指定一個順序號,接收方在收到TCP數據包后按照順序將數據包進行重組,重組后的數據全都是二進制數據,且每次收到的二進制數據之間沒有明顯的分界。基于這種工作機制,TCP在三種情況下發生黏包問題:

①當單個數據包較小時,接收方可能一次性讀取了多個包的數據;

②當整體數據較大時,接收方可能一次性僅讀取了一個包的一部分內容;

③另外TCP協議為提高效率,增加了一種優化機制,會將數據小且發送間隔短的數據合并發送,該機制也會導致發送方將兩個數據包粘在一起發送。

也就是說,TCP傳輸數據是可靠的,但是會黏包。

4.發送方出現的黏包

服務器端:

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("收到的第一條數據:",data1)
print("收到的第二條數據:",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()

服務器端接收到的數據:

由于客戶端兩條數據發送間隔太短且數據包太小,被服務器端誤認為是一條數據。

5. 接收方出現的黏包

服務器端:

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) #每次只接收三個字節,接收不完整
time.sleep(6)
print("收到的第一條數據:",data1)
?
data2 = new_socket.recv(10)
#接收第一次未接收的數據,若有空間,會繼續接收新數據
print("收到的第二條數據:",data2)
?
new_socket.close()
server_socket.close()

客戶端:

from socket import *
#通過time模塊使客戶端發送多個數據包時,時間間隔變長
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) #讓當前線程休眠5秒
client_socket.send('word'.encode('utf-8'))
?
client_socket.close()

服務器端接收到的數據:

6.黏包的成因

①服務器端出現黏包:接收方不知道消息之間的界限,不知道一個消息要提取多少字節的數據造成的;

②客戶端出現黏包:TCP在發送數據少且間隔時間短的數據包時,會將幾條合并一起發送。

原文鏈接:https://blog.csdn.net/qq_40523659/article/details/121695950

欄目分類
最近更新