TCP的粘包现象
看面經(jīng)時,看到有面試官問TCP的粘包問題。想起來研一做購物車處理數(shù)據(jù)更新時遇到粘包問題,就總結(jié)一下吧。
1 什么是粘包現(xiàn)象
TCP粘包是指發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時粘成一包,從接收緩沖區(qū)看,后一包數(shù)據(jù)的頭緊接著前一包數(shù)據(jù)的尾。
2 為什么出現(xiàn)粘包現(xiàn)象
(1)發(fā)送方原因
我們知道,TCP默認會使用Nagle算法。而Nagle算法主要做兩件事:1)只有上一個分組得到確認,才會發(fā)送下一個分組;2)收集多個小分組,在一個確認到來時一起發(fā)送。
所以,正是Nagle算法造成了發(fā)送方有可能造成粘包現(xiàn)象。
(2)接收方原因
TCP接收到分組時,并不會立刻送至應(yīng)用層處理,或者說,應(yīng)用層并不一定會立即處理;實際上,TCP將收到的分組保存至接收緩存里,然后應(yīng)用程序主動從緩存里讀收到的分組。這樣一來,如果TCP接收分組的速度大于應(yīng)用程序讀分組的速度,多個包就會被存至緩存,應(yīng)用程序讀時,就會讀到多個首尾相接粘到一起的包。
3 什么時候需要處理粘包現(xiàn)象
(1)如果發(fā)送方發(fā)送的多個分組本來就是同一個數(shù)據(jù)的不同部分,比如一個很大的文件被分成多個分組發(fā)送,這時,當(dāng)然不需要處理粘包的現(xiàn)象;
(2)但如果多個分組本毫不相干,甚至是并列的關(guān)系,我們就一定要處理粘包問題了。比如,我當(dāng)時要接收的每個分組都是一個有固定格式的商品信息,如果不處理粘包問題,每個讀進來的分組我只會處理最前邊的那個商品,后邊的就會被丟棄。這顯然不是我要的結(jié)果。
4 如何處理粘包現(xiàn)象
(1)發(fā)送方
對于發(fā)送方造成的粘包現(xiàn)象,我們可以通過關(guān)閉Nagle算法來解決,使用TCP_NODELAY選項來關(guān)閉Nagle算法。
(2)接收方
遺憾的是TCP并沒有處理接收方粘包現(xiàn)象的機制,我們只能在應(yīng)用層進行處理。
(3)應(yīng)用層處理
應(yīng)用層的處理簡單易行!并且不僅可以解決接收方造成的粘包問題,還能解決發(fā)送方造成的粘包問題。
解決方法就是循環(huán)處理:應(yīng)用程序在處理從緩存讀來的分組時,讀完一條數(shù)據(jù)時,就應(yīng)該循環(huán)讀下一條數(shù)據(jù),直到所有的數(shù)據(jù)都被處理;但是如何判斷每條數(shù)據(jù)的長度呢?
兩種途徑:
1)格式化數(shù)據(jù):每條數(shù)據(jù)有固定的格式(開始符、結(jié)束符),這種方法簡單易行,但選擇開始符和結(jié)束符的時候一定要注意每條數(shù)據(jù)的內(nèi)部一定不能出現(xiàn)開始符或結(jié)束符;
2)發(fā)送長度:發(fā)送每條數(shù)據(jù)的時候,將數(shù)據(jù)的長度一并發(fā)送,比如可以選擇每條數(shù)據(jù)的前4位是數(shù)據(jù)的長度,應(yīng)用層處理時可以根據(jù)長度來判斷每條數(shù)據(jù)的開始和結(jié)束。
當(dāng)時在做購物車的時候,我最開始的做法是設(shè)置開始符(0x7e)和結(jié)束符(0xe7),但在測試大量數(shù)據(jù)的時候,發(fā)現(xiàn)了數(shù)據(jù)異常。正如我所猜測,在調(diào)試過程中發(fā)現(xiàn)某些數(shù)據(jù)內(nèi)部包含了它們。因為要處理的數(shù)據(jù)是量非常龐大,為做到萬無一失,最后我采用了發(fā)送長度的方式。再也沒有因為粘包而出過問題。
from:?https://www.cnblogs.com/qiaoconglovelife/p/5733247.html?
總結(jié)
- 上一篇: TCP通信粘包问题分析和解决
- 下一篇: TCP通讯处理粘包详解