粘包 拆包(分包) 半包

粘包、拆包、半包理解

TCP是一種面向流的網絡層傳輸協議,在使用TCP做爲傳輸層協議時,可保證數據的順序性和可靠性。網絡

應用層在使用TCP協議傳輸數據時,可採起兩種方式:blog

  • 短連接:客戶端同服務端完成一次通訊(客戶端只發送一次請求,並接收到響應),關閉TCP鏈接;
  • 長鏈接:客戶端持續同服務端進行通訊(客戶端不停的發送請求,並接收到響應),不關閉TCP鏈接;

使用短鏈接時,可經過TCP鏈接是否關閉判斷是否完成了一次請求響應通訊。但每次請求必須重建TCP鏈接,會致使請求響應一會會存在一個TCP握手延時。所以常常使用長鏈接進行較高頻率的請求響應通訊。coding

但在使用長鏈接時,因爲客戶端可能會發送多個請求,服務端會同時持續收到數據。服務端接收到的數據中可能包含多個請求數據,此時請求數據是粘連在一塊兒的(粘包),須要進行拆分(拆包)。請求

還有一種狀況,服務端接收到的數據中包含一個不完整的請求數據,剩餘數據還未接收到(半包),服務端須要繼續接收數據直到接收完整請求數據。方法

  • 粘包:只會在長鏈接通訊方式中存在,不一樣的請求數據會被服務端同時接收到,而服務端暫時沒法將其請求數據區分爲請求1或者請求2。
  • 拆包:將粘連在一塊兒的不一樣請求數據進行拆分
  • 半包:服務端接收到的請求數據不完整,剩餘數據正在傳輸過程當中。

粘包、拆包、半包圖示

粘包:服務端接收到的請求數據牢牢挨着,暫時沒法分離。im

 

拆包:服務端將接收到的數據拆分爲不一樣的請求數據通信

 

半包:拆包過程當中發現某個請求數據不完整,須要繼續接收數據。數據

如何拆包、判斷半包

如何判斷不一樣請求數據的起始和結束位置,是拆包和判斷半包的關鍵。客戶端

經常使用的方法有兩種:協議

  • 包頭(包含包體長度)+包體
  • 包頭(包含預約義的界定標識)+包體+包尾(包含預約義的界定標識)

第一種方法,讀取固定長度的包頭後,可根據包頭中指定的包體長度讀取包體,直到讀取到完整的包體。

  • 問題:若是包頭中的包體長度同實際的包體長度不附,會致使後續的全部數據拆包都出現問題,且沒法恢復。

第二種方法,在持續讀取數據時,須要判斷讀取的數據中是否出現了界定標識,出現了便可判斷是否已到舊包的包尾或者新包的包頭。包頭和包尾至少存在一個。

  • 問題:讀取過程當中需一直判斷界定標識,在高速傳輸數據時,會致使微小的處理延時。

 

http協議能夠說是以上兩種方法的結合,http header信息經過第二種方法獲取,兩個CRLF後標識http header結束,http response body經過第一種方法獲取(content-length),也會採用第一二種結合方式獲取(transfer-Encoding: chunked)。

相關文章
相關標籤/搜索