成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 TCP 粘包是正常現象

網絡
TCP 粘包 并不是因為協議本身有 “問題”,而是一種 “正常現象”, 因為 TCP 是面向字節流的協議,數據之間沒有所謂 “邊界”,所以數據粘包之后的 “拆包” 工作應該 (也必須) 由應用層完成。

一、TCP 粘包現象

TCP 粘包是指發送方發送了若干數據包,但是到達接收方之后,數據包的內容全部 “粘連” 在了一起,每個數據包的數據結尾直接和下個數據包的數據連在了一起,無法正常區分。

下面的圖片展示了一個 TCP 粘包現象,正常的 3 個數據包因為粘包,被連在了一起,看起來像是一個數據包,結果就很感人了 ...

二、TCP 粘包/拆包 原因


TCP 粘包 并不是因為協議本身有 “問題”,而是一種 “正常現象”, 因為 TCP 是面向字節流的協議,數據之間沒有所謂 “邊界”,所以數據粘包之后的 “拆包” 工作應該 (也必須) 由應用層完成。


TCP 采用 “異步” 方式發送應用數據,也就是說,當應用程序中調用 Send(packet) 發送數據時,雖然 Send 函數會立即返回,但是數據并不一定已經到達通信對方了。應用數據具體什么時候發,由應用層下面的傳輸層 TCP 說了算,TCP 使用了 3 個主要機制 (確認與重傳、滑動窗口流量控制、擁塞控制) 來實現可靠性傳輸,保證應用數據的可靠傳輸和 應用層數據發送順序和到達順序一致的語義保證。

下面來展開說一下可能導致 粘包/拆包 問題的原因。

1. 面向字節流的工作特性

TCP 作為傳輸層,并不了解 (也不關心) 應用層數據的上下文含義,它只會根據通信雙方約定的 MSS[1] 對發送緩沖區的數據包進行拆分。

所以在應用層的視角來看,一個完整的數據包 (可能是一段聊天文字、一個圖片、一個視頻) 可能會經歷不同的發送過程:

  • 如果 MSS 較小,一個完整的數據包會被 TCP 拆分成多個更小的 數據包進行發送,產生拆包現象
  • 如果 MSS 較大,多個完整的數據包會被 TCP 合并為一個更大的 數據包進行發送,產生粘包現象

2. 緩沖機制

TCP 在發送數據時,會將數據放入發送緩沖區;在接收數據時,會將數據放入接收緩沖區。TCP 會盡可能地將發送緩沖區中的數據打包成一個或多個數據包發送出去,而接收方在讀取數據時,也會盡量將接收緩沖區中的數據全部讀取出來。這種機制可能導致發送方一次發送的多個數據包被接收方一次性讀取,從而引發粘包問題。

  • TCP 發送方會將數據放入 發送緩沖區
  • TCP 接收方會將數據放入 接收緩沖區

為了盡可能提升發送數據和接受處理數據的性能,作為發送方來講:

  • 如果要發送的數據小于發送緩沖區大小,TCP 會將多次要發送的數據,全部寫入發送緩沖區,然后一起發送,產生粘包現象
  • 如果要發送的數據大于發送緩沖區大小,TCP 會將要發送的數據進行切分,滿足寫入發送緩沖區的條件,然后發送,產生拆包現象

作為接收方來講:

  • 如果應用層沒有及時處理接收緩沖區的數據,產生粘包現象

3. Nagle 算法

Nagle 算法原理: 發送方已經發送數據還未被接收方確認之前,期間如果又有小數據生成,先把小數據收集起來,湊滿一個 MSS (最大報文段大小) 或者收到接收方 Ack 后再一起發送。通過將小數據包積累成較大的數據包后再發送,從而提高網絡效率。

很顯然,根據 Nagle 算法的工作機制,在頻繁發送小的數據包時 (例如 Telnet, SSH 終端),會產生粘包現象。

下面是在 Go 語言中關閉 TCP Nagle 算法的示例代碼。

package main

func main() {
    conn, _ := net.Dial("tcp", "dbwu.tech:443")

    fd := conn.(*net.TCPConn).File()
    // 關閉 Nagle 算法
    syscall.SetsockoptInt(int(fd.Fd()), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1)
}

? 單純關閉 Nagle 算法并不能解決粘包問題,讀者思考一下為什么?

?? 綜上所述,因為應用層和傳輸層工作方式上的差異,所以就導致了所以的 “TCP 粘包/拆包” 問題。

三、解決方案

既然拆包必須由應用層來完成,那么按照數據處理的思路,只要應用程序對 TCP 的字節流數據能夠區分單個消息的標志和邊界,那么應用程序就可以將粘包后的數據分割為正常的單個消息,粘包問題自然迎刃而解。

目前業界主要采用的解決方案:

(1) 設置消息固定長度: 發送方可以將每個消息設置為固定的長度 (對于長度不夠的消息可以使用 0 進行填充),接收方從緩沖區讀取數據時,每次都讀取固定的長度,這樣很自然就把單個消息拆分出來

(2) 設置消息分隔符: 發送方在將單個消息末尾追加分隔符,用來分區單個消息,接收方從緩沖區讀取數據后,根據分隔符將讀取到的數據切割成一個個單條消息

當然,分隔符很容易出現在要發送的應用數據中,這樣就產生了沖突,無法進行正常拆包,所以實際項目中很少使用這種方式。

(3) 設置消息頭部格式: 將消息分為消息頭部和消息體,消息頭中包含表示消息總長度(或者消息體長度,例如 HTTP 中的 Content-Length)字段,接收方首先讀取消息頭部,然后根據消息長度字段 讀取具體的消息體內容,這也是最常用的方式

(4) 特定消息格式: 例如將單個消息固定為 JSON 格式,接收方從緩沖區讀取數據后,根據讀取到的數據能否被解析成合法的 JSON 來判斷消息是否結束,當然,實際項目中很少使用這種方式

??注意,以上提到的解決方案通常由網絡編程框架 (例如 Java 的 Netty, Golang 的 gnet) 來實現,而不是由應用程序中的業務代碼來實現。

四、不同應用場景的下的應對方案

完全禁止 粘包/拆包 的場景:

  • 低延遲要求: 在線游戲、股票交易
  • 小數據頻繁傳輸,例如 Telnet, SSH 終端

可以忽視 粘包/拆包 的場景:

  • 小數據傳輸,且兩次傳輸之間的時間間隔很大,例如 5 秒/次 的心跳
  • 使用已經處理了粘包問題的應用層協議,例如 HTTP 使用響應頭中的 Content-Length 作為消息分隔符
  • 傳輸數據只需要保證順序即可,無需區分邊界,例如大文件傳輸,每個數據包都是文件的一小部分而已,因為 TCP 保證了傳輸順序性,所以接收方只需要讀取數據,然后追加到已有數據的后面即可

五、UDP 有粘包/拆包 問題嗎?

UDP 是無連接的協議,每個數據報都是獨立傳輸的,接收方收到的數據報和發送方發送的數據報是一一對應的 (但是報文到達時間上可能會出現亂序),不需要建立連接,也不需要維護連接的狀態,換句話說,選擇 UDP 協議時,應用層必須完成數據的拆包工作,所以自然也就不存在 粘包/拆包 問題了。

責任編輯:趙寧寧 來源: 洋芋編程
相關推薦

2020-03-10 08:27:24

TCP粘包網絡協議

2021-07-15 10:35:16

NettyTCPJava

2024-12-19 11:00:00

TCP網絡通信粘包

2019-10-17 11:06:32

TCP粘包通信協議

2022-08-01 07:07:15

粘包半包封裝

2021-03-09 22:30:47

TCP拆包協議

2019-10-24 07:35:13

TCP粘包Netty

2020-12-30 09:04:32

Go語言TCPUDP

2022-04-28 08:38:09

TCP協議解碼器

2020-12-23 07:53:01

TCP通信Netty

2024-08-16 21:47:18

2020-01-13 10:16:53

TCPUDP協議

2020-01-15 08:42:16

TCP三次握手弱網絡

2020-04-01 15:30:19

TCPUDP服務器

2021-07-06 17:13:08

NVMe存儲協議數據中心

2020-01-06 15:23:41

NettyTCP粘包

2022-07-27 07:36:01

TCP可靠性

2019-09-30 09:41:04

五層協議OSITCP

2019-10-25 00:32:12

TCP粘包Netty

2025-03-21 10:31:44

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美综合在线视频 | 伊人艹| 免费一级片 | 久久久久久91 | 一区二区三区精品视频 | 亚洲一区二区久久久 | 国产视频中文字幕 | 精品不卡 | 国产一区二区美女 | 91欧美精品成人综合在线观看 | 日韩av免费看 | 日本亚洲精品成人欧美一区 | 国产精品免费观看视频 | 四虎影视免费观看 | 在线播放一区二区三区 | 欧美日韩成人影院 | 91偷拍精品一区二区三区 | 黄色在线免费观看 | 在线精品亚洲欧美日韩国产 | 精品国产18久久久久久二百 | 午夜影院污 | 在线视频 中文字幕 | 黑人巨大精品欧美一区二区一视频 | 成年人在线观看视频 | 涩涩片影院 | 中文字幕一区二区三区不卡在线 | 久久一| 在线观看成人小视频 | 日韩一区二区三区视频在线观看 | 精品国产乱码久久久久久蜜退臀 | 97超碰人人| 精品欧美一区二区精品久久久 | 国产欧美一区二区三区日本久久久 | 91精品国产色综合久久 | 成人午夜激情 | 久久亚洲一区二区三区四区 | 美女国产| 成人动漫视频网站 | 国产三级日本三级 | aaa大片免费观看 | 国产美女自拍视频 |