網站首頁 編程語言 正文
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
相關推薦
- 2023-06-05 Python?socket之TCP通信及下載文件的實現_python
- 2022-09-05 C語言之關于二維數組在函數中的調用問題_C 語言
- 2022-06-12 python文件操作的基礎詳細講解(write、read、readlines、readline)_p
- 2022-09-21 jquery實現網頁左側導航菜單欄_jquery
- 2022-05-17 bat批處理腳本中文亂碼的解決_DOS/BAT
- 2022-08-06 .Net?Core中使用EFCore生成反向工程_實用技巧
- 2022-03-22 C#中數據類型的轉換介紹_C#教程
- 2022-07-07 Python如何使用type()函數查看數據的類型_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支