我們在涉及TCP協(xié)議的應(yīng)用中,經(jīng)常會出現(xiàn)粘包的問題。所謂粘包,簡單地講,就是我有兩條消息,明明發(fā)送端的代碼是分兩次發(fā)送的,但是在接收端卻一次性就接收到了兩條消息。這個情況不管是在嵌入式行業(yè)還是在互聯(lián)網(wǎng)行業(yè),都非常的普遍。
那就需要先了解 TCP協(xié)議的定義。TCP(Transmission Control Protocol)傳輸控制協(xié)議,是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
其中跟粘包關(guān)系最大的就是基于字節(jié)流這個特點。字節(jié)流可以理解為一個雙向的通道里流淌的數(shù)據(jù),這個數(shù)據(jù)其實就是我們常說的二進制數(shù)據(jù),簡單來說就是一大堆 01 串。這些 01 串之間沒有任何邊界。
應(yīng)用層傳到TCP協(xié)議的數(shù)據(jù),不是以消息報為單位向目的主機發(fā)送,而是以字節(jié)流的方式發(fā)送到下游,這些數(shù)據(jù)可能被切割和組裝成各種數(shù)據(jù)包,接收端接收到這些數(shù)據(jù)包后沒有正確還原之前的消息,因此出現(xiàn)粘包現(xiàn)象。
那為什么會出現(xiàn)不能正確還原的情況呢?主要有兩個方面的原因:
發(fā)送端在組裝消息的時候,就把幾個小包合成一包了,這樣接收端自然無法解析出小包。這對應(yīng)的就是Nagle算法。因為TCP和Nagle算法都是上個世紀的產(chǎn)物了,在早期的網(wǎng)絡(luò)中這樣做,可以顯著地減小網(wǎng)絡(luò)的壓力。否則頻繁地發(fā)送僅有幾個字節(jié)的小包,會嚴重浪費網(wǎng)絡(luò)IO性能。
但是在現(xiàn)代互聯(lián)網(wǎng)中,網(wǎng)絡(luò)性能已經(jīng)有了大幅提升,似乎Nagle 算法提升的那么一點IO性能就不是那么重要了,反而由于等待數(shù)據(jù)來合并的操作,會導(dǎo)致傳輸延遲變大,在網(wǎng)絡(luò)游戲應(yīng)用時,就會非常影響體驗。所以現(xiàn)在一般都會關(guān)掉它。
接收端接收到消息以后,應(yīng)用層總是不能立即取走數(shù)據(jù),總是會有接收緩沖區(qū)的存在。如果兩條獨立的消息進入緩沖區(qū)的間隔太小,應(yīng)用層不能在兩次消息中間取走上一條消息,那么下次讀取的時候,就勢必會把兩包消息同時讀出來,這也會導(dǎo)致粘包。
而且這個情況并不能通過讓發(fā)送端在時間上均勻發(fā)包來避免,因為網(wǎng)絡(luò)不穩(wěn)定情況的存在,即使是時間上均勻發(fā)送的數(shù)據(jù)包,在接收端看來也可能是隨機出現(xiàn)的。
根據(jù)以上分析,我們不難發(fā)現(xiàn),想要杜絕粘包的問題出現(xiàn),基本上是不可能的。即使發(fā)送端和接收端都能自己控制,但是網(wǎng)絡(luò)傳輸?shù)倪^程也是很難控制的。
但是即使粘包的問題存在,也不影響我們大規(guī)模的使用TCP協(xié)議。因為這個問題在應(yīng)用層非常好處理。大致有兩種思路:
這樣,當應(yīng)用層檢測到特殊的分隔符后,便知道這是一包得到開始和結(jié)束,就可以進行分片等操作,問題便迎刃而解。
不過這樣存在一些弊端。比如定義分隔符為“12345678”,那如果消息內(nèi)容里面出現(xiàn)“12345678”的字符串呢?這樣就會導(dǎo)致消息被異常的切片,導(dǎo)致接收到的消息錯誤。但假如自己能夠控制消息的內(nèi)容,保證里面不會出現(xiàn)“12345678”的內(nèi)容,則此方法較為靈活。
根據(jù)約定好的長度的字段,讀取消息長度的信息,再根據(jù)消息長度信息讀取消息內(nèi)容。這也是一種非常常用的方法,在很多協(xié)議中都有體現(xiàn)。
發(fā)送端給每個數(shù)據(jù)包添加包首部,首部中應(yīng)該至少包含數(shù)據(jù)包的長度,這樣接收端在接收到數(shù)據(jù)后,就可以通過讀取包首部的長度字段,知道每一個數(shù)據(jù)包的實際長度。
以上就是本期關(guān)于解決TCP粘包問題的內(nèi)容,小編碼字不易,求個點贊支持!我們下期見~~
今天的分享就到這里啦,EBYTE每一天都致力于更好的助力物聯(lián)化、智能化、自動化的發(fā)展,提升資源利用率,更多產(chǎn)品更多資料,感興趣的小伙伴可以登錄我們的億佰特官網(wǎng)和企業(yè)公眾號(微信號:cdebyte)進行了解,也可以直接撥打400電話咨詢技術(shù)專員!
相關(guān)閱讀:
1、基礎(chǔ)通信協(xié)議棧:TCP協(xié)議、IP協(xié)議詳解
7 X 24 銷售服務(wù)熱線
4000-330-990深圳辦事處柯經(jīng)理:18218726658 杭州辦事處戴經(jīng)理:17512568697
常州辦事處崔經(jīng)理:15906110783 南京辦事處葛經(jīng)理:17626012283
業(yè)務(wù)郵箱:support@cdebyte.com
全國銷售投訴電話:19934352316
地址:四川省成都市高新西區(qū)西區(qū)大道199號B5棟(前臺座機:028-61543675)
?? 成都億佰特電子科技有限公司【版權(quán)所有】 蜀ICP備13019384號-3