TCP組包問題及處理方法
問題的表述
問題的背景是這樣的:有一個系統,那有後臺伺服器,也有移動端的客戶端。當客戶端上線時,伺服器會將指定的資料庫的資料傳送給客戶端,客戶端解析後呈現。
但是,有一天客戶端開發跟我反映一個奇怪的問題:之前客戶端一上線就收到伺服器發來的資料,現在客戶端收到了資料,但是解析出問題了。但是前後端的程式碼都沒有改啊,只是要傳送的資料是新新增的,並且比之前的測試資料要大。
原因的剖析
根據他的描述,很明顯問題出在了要傳送的資料上。由於之前是測試資料,並不會放過大的資料到後臺資料庫,現在放上去的是真實資料,要比測試資料大好多。
於是我就重新拾起了塵封已久的tcp/ip協議的書,也試著在網上尋找答案。最終我知道了我們這個問題叫做tcp協議的組包問題。
什麼叫tcp的組包問題呢?簡單的說就是tcp協議把過大的資料包分成了幾個小的包傳輸,客戶端要把同一組的資料包重新組合成一個完整的資料包。
具體點的解釋:
首先我們要知道MTU(最大傳輸單元)。IP分片在乙太網上,由於電氣限制,一幀不能超過1518位元組,除去乙太網幀頭14位元組(mac地址等)和幀尾4位元組校驗,不考慮PPPoE協議(讀者自行了解這是什麼鬼)的8個位元組,還剩1500位元組,這個大小稱為MTU(最大傳輸單元)。
這1500還包含20位元組IP頭,8位元組UDP頭或者20位元組TCP頭。所以真正的一次傳送的資料包,UDP為1500-28=1472位元組,TCP為1500-40=1460位元組。
當然我們要知道tcp是可靠傳輸協議,以位元組流的形式傳輸資料的,什麼意思呢?就是他可以允許超過1452位元組的資料進行傳輸,因為他會把它切分成多個包,然後用序號進行排序,從而表明了這幾個包是同一組資料。
但是UDP是不可靠傳輸,它一次性就只能發那麼多了,超過的他就不允許發了,所以他效率高,傳送一次就是一個完整的資料,接收方直接拿去解析就可以了。(UDP和TCP還有很多不同的優缺點,讀者感興趣可以自行了解)
所以瞭解了這些之後對於上面描述的問題現象也就不難解釋了,由於我們後臺伺服器傳送的資料包過大,比如有5000位元組,那麼tcp協議就會把它分成1460+1460+1460+620位元組,分四個包傳送給客戶端,客戶端單單解析一個數據包得到的資料肯定是不完整的,要是傳輸的資料是帶一定的結構的話就會解析出錯了。
傳送端處理方法
那麼知道了產生這個問題的原因,又該怎麼解決這個問題呢。我在一個網站上看到有如下回答:連結
一 可以每次傳送同樣大小的包,過大的包不予傳送,過小的包,後面部分用固定的字元’\0’進行填充。
二 將流按字元處理,抽出一個字元做轉義字元(通常Java用’\’來做轉義字元,比如”\n”表示換行)。
三 在傳送方傳送一個包的時候,先將這個包的長度傳送給對方(一般是4個位元組表示包長),然後再將包的內容傳送過去.接收方先接收4個位元組,看看包的長度,然後按照長度來接收包。
於是我採用了最後一種解決辦法,伺服器其傳送的資料中,前4個位元組為需要傳送的資料的位元組數,如上所說,這樣的做法其實就是在TCP協議之上又在封裝了一層,只不過很簡單明瞭。
接收端處理方法
因為TCP會對收到的報文段進行重新排序,然後再交給應用層處理,所以可以用以下的邏輯作為接收端的處理方法。
演算法(裝逼專用詞):
1.設定全域性標量flag最為標識位,初始值為0;設定全域性變數L,初始值為0。
2.取快取區資料包,判斷標識位,若為0,進入步驟3;若為1,傳遞引數L,進入步驟4。
3.解析資料前4個位元組,得到位元組數L後與當前資料塊剩下的位元組數M比較。若相等,執行步驟5。若L>M,則設定標識位為1,暫時儲存這M位元組資料,傳引數L=L-M,執行步驟2。
4.比較L與當前資料包的大小M,若相等,執行步驟5;若L>M,暫時儲存著M位元組資料,傳引數L=L-M,執行步驟2。
5.呼叫解析函式正常解析,設定標識位為0。
流程圖如下:
總結
事實上,tcp傳輸資料中還存在粘包、分包、半包的問題。傳送端的解決辦法還是一樣的,但是接收端的處理邏輯略有不同,這個就等到下一篇博文中再寫吧。
相關推薦
TCP組包問題及處理方法
問題的表述 問題的背景是這樣的:有一個系統,那有後臺伺服器,也有移動端的客戶端。當客戶端上線時,伺服器會將指定的資料庫的資料傳送給客戶端,客戶端解析後呈現。 但是,有一天客戶端開發跟我反映一個奇怪的問題:之前客戶端一上線就收到伺服器發來的資料,現在客
Eclipse java文件、包、工程左下角有感嘆號原因及處理方法
技術分享 image 指定元素 有感 blog 窗口 處理 import 引用 先想如圖所示: 原因:多是import引用了無用的類,或集合沒指定元素的類型 解決方案如下: 1、可逐一到出現感嘆號的java文件中去處理 2、可根據markers窗口下的Java Probl
關於TCP粘包,拆包及解決方法
在進行Java NIO學習時,發現,如果客戶端連續不斷的向服務端傳送資料包時,服務端接收的資料會出現兩個資料包粘在一起的情況,這就是TCP協議中經常會遇到的粘包以及拆包的問題。 我們都知道TCP屬於傳輸層的協議,傳輸層除了有TCP協議外還有UDP協議。那麼UDP是否會發生粘包或拆包的現象呢?答案
TCP粘包,拆包及解決方法
在進行Java NIO學習時,發現,如果客戶端連續不斷的向服務端傳送資料包時,服務端接收的資料會出現兩個資料包粘在一起的情況,這就是TCP協議中經常會遇到的粘包以及拆包的問題。 我們都知道TCP屬於傳輸層的協議,傳輸層除了有TCP協議外還有UDP協議。那麼UDP
TCP粘包,拆包及解決方法、丟包的原因及解決辦法
粘包、拆包發生原因 發生TCP粘包或拆包有很多原因,現列出常見的幾點,可能不全面,歡迎補充, 1、要傳送的資料大於TCP傳送緩衝區剩餘空間大小,將會發生拆包。 2、待發送資料大於MSS(最大報文長度),TCP在傳輸前將進行拆包。 3、要傳送的資料小於
銳捷Windows認證客戶端常見問題及處理方法
windows 銳捷 認證客戶 1:無法開機自啟動?A:在客戶端設置界面中勾選開機自動運行項,並檢查系統或第三方軟件(主要是第三方WIFI或外掛之類軟件)是否配置了阻止客戶端的自動運行,可通過卸載或徹底停止相關軟件然後測試客戶端來確認。2:無法接收到通告消息?A:在客戶端設置界面中勾選校園網消息提
關於SIGSEGV錯誤及處理方法
pre 數據訪問 gdb bus 程序 調用棧 bsp 處理 clas http://blog.csdn.net/brace/article/details/1102422 今天編程遇到了SIGSEGV錯誤,比較困惑,所以找了些資料,總結一下: (1)官方說法是: SIG
常見的手機小故障及處理方法
kkk 常見的手機小故障及處理方法 世界在變,社會在發展,而現如今的手機已經成為人們生活中不可或缺的一部分了。眾所周知不管是什麽東西用久了都會出現或大或小的毛病。如人會生病,手機也和人是一樣的用久了也會出現一些小毛病的。當手機出現問題時,不要著急,深圳莊文展國際手
mybatis報錯java.lang.UnsupportedOperationException原因及處理方法
起因 今天在請求資料庫資料時報錯java.lang.UnsupportedOperationException,從字面上理解錯誤的含義就是不支援的操作異常,後面定位到錯誤發生在資料庫sql語句中,具體原因就是resultType="java.util.List"有問題。返回的結果是一
C#.網路程式設計 Tcp基礎(二) TCP組包、粘包、拆包的原理
一、TCP粘包,拆包及解決方法 轉https://blog.csdn.net/scythe666/article/details/51996268 以下是轉發的部分內容 我們都知道TCP屬於傳
開發過程中遇到的異常及處理方法
------Mapped Statements collection already contains value for com.chong.model.AccountMapper.checkAccount ------錯誤原因是由於使用mybatis的AccountMapper.xml
Socket錯誤詳解及處理方法
例如錯誤程式碼10061, 說明伺服器已經找到,但連線被伺服器拒絕, 連線失敗原因可能是: 埠號設定錯誤; 2.伺服器沒有處於監聽狀態 (即ServerSocket –>Active=true); 3.資料包被伺服器端的防火牆過濾掉。 附:Socket常見錯誤程式碼與描述 Sock
raid問題總彙及處理方法
1.新建raid陣列卷組 (在伺服器上增加新的硬碟,原raid陣列及伺服器資料儲存不變的情況下,將新加硬碟做成單獨的raid陣列) a.開機按 ctrl+R 進入raid介面(注意下圖最後一行的configration utility ) b.在VD Mgmt選單下按F2
Nginx常見錯誤及處理方法
原文轉載:https://www.cnblogs.com/liyongsan/p/6795851.html 404 bad request 一般原因:請求的Header過大。 解決方法:配置nginx.conf相關設定 client_header_buffer_size 
MTK camera CTS 除錯遇到的問題及處理方法
一、CTS camera幀率測試不過 log: Wanted *at least* 3 times: -> at android.hardware.camera2.cts.RobustnessTest.testOutputCombination(Ro
mysql-bin.000001檔案的來源及處理方法
用ports安裝了MySQL以後,過一段時間發現/var空間不足了,查一下,會發現是mysql-bin.000001、mysql-bin.000002等檔案佔用了空間,那麼這些檔案是幹嗎的?這是資料庫的操作日誌,例如UPDATE一個表,或者DELETE一些資料,即使該語句沒有
git部署自動同步站點常見問題及處理方法
說明 本人自己搭建了git伺服器並設定了程式碼提交後自動同步至站點目錄,在使用的過程中出現了一些問題,總結了一下,方便大家參考,如有問題,請大家聯絡我或在評論中指正。 問題一 問題描述: 程式碼提交(
變頻電源六大故障及處理方法
工業變頻電源,日夜執行,經過使用變頻電源積累的引數變化,故障是難以避免的。變頻電源均有欠電壓保護功能、過電流保護功能、過壓保護功能、程式保護功能、過高溫保護功能、極性保護功能,各廠家生產的變頻電源基本具備這些保護功能。當變頻電原始碼線上執行時出現異常資訊或故障時,變頻電源發報警。那麼出現了故障我們應該怎麼去處
【轉】TCP粘包問題解決方法之\n\r
該方案,每次讀取時當讀到‘\n’換行符時,讀取該行 伺服器端: [cpp] view plain copy #include<uni
openfire報錯及處理方法
一、openfire配置完,執行時控制檯報如下錯誤: 一大堆東西,比較有用的就是XML properties file does not exist:openfire.xml 這說明Openfire的Home沒有設定或者設定不正確 選中專案,點選run -> ru