網站首頁 編程語言 正文
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-03-16 numpy如何獲取array中數組元素的索引位置_python
- 2022-12-27 C語言實現二叉樹鏈式結構的示例詳解_C 語言
- 2022-12-22 python實現將list拼接為一個字符串_python
- 2022-11-15 C++構造析構賦值運算函數應用詳解_C 語言
- 2022-04-08 WPF布局及布局容器介紹_基礎應用
- 2022-10-08 如何在React項目中引入字體文件并使用詳解_React
- 2022-06-29 python人工智能tensorflow函數tf.layers.dense使用方法_python
- 2022-06-29 Oracle數據庫之PL/SQL使用流程控制語句_oracle
- 最近更新
-
- 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同步修改后的遠程分支