我們?cè)谏婕癟CP協(xié)議的應(yīng)用中,經(jīng)常會(huì)出現(xiàn)粘包的問題。所謂粘包,簡(jiǎn)單地講,就是我有兩條消息,明明發(fā)送端的代碼是分兩次發(fā)送的,但是在接收端卻一次性就接收到了兩條消息。這個(gè)情況不管是在嵌入式行業(yè)還是在互聯(lián)網(wǎng)行業(yè),都非常的普遍。
TCP協(xié)議為什么粘包?
那就需要先了解 TCP 的定義。TCP(Transmission Control Protocol)傳輸控制協(xié)議,是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。其中跟粘包關(guān)系最大的就是基于字節(jié)流這個(gè)特點(diǎn)。字節(jié)流可以理解為一個(gè)雙向的通道里流淌的數(shù)據(jù),這個(gè)數(shù)據(jù)其實(shí)就是我們常說的二進(jìn)制數(shù)據(jù),簡(jiǎn)單來說就是一大堆 01 串。這些 01 串之間沒有任何邊界。應(yīng)用層傳到 TCP 協(xié)議的數(shù)據(jù),不是以消息報(bào)為單位向目的主機(jī)發(fā)送,而是以字節(jié)流的方式發(fā)送到下游,這些數(shù)據(jù)可能被切割和組裝成各種數(shù)據(jù)包,接收端接收到這些數(shù)據(jù)包后沒有正確還原之前的消息,因此出現(xiàn)粘包現(xiàn)象。那為什么會(huì)出現(xiàn)不能正確還原的情況呢?主要有兩個(gè)方面的原因:
1. 發(fā)送端的原因發(fā)送端在組裝消息的時(shí)候,就把幾個(gè)小包合成一包了,這樣接收端自然無法解析出小包。這對(duì)應(yīng)的就是Nagle 算法。因?yàn)門CP和Nagle 算法都是上個(gè)世紀(jì)的產(chǎn)物了,在早期的網(wǎng)絡(luò)中這樣做,可以顯著地減小網(wǎng)絡(luò)的壓力。否則頻繁地發(fā)送僅有幾個(gè)字節(jié)的小包,會(huì)嚴(yán)重浪費(fèi)網(wǎng)絡(luò)IO性能。但是在現(xiàn)代互聯(lián)網(wǎng)中,網(wǎng)絡(luò)性能已經(jīng)有了大幅提升,似乎Nagle 算法提升的那么一點(diǎn)IO性能就不是那么重要了,反而由于等待數(shù)據(jù)來合并的操作,會(huì)導(dǎo)致傳輸延遲變大,在網(wǎng)絡(luò)游戲應(yīng)用時(shí),就會(huì)非常影響體驗(yàn)。所以現(xiàn)在一般都會(huì)關(guān)掉它。2. 接收端的原因接收端接收到消息以后,應(yīng)用層總是不能立即取走數(shù)據(jù),總是會(huì)有接收緩沖區(qū)的存在。如果兩條獨(dú)立的消息進(jìn)入緩沖區(qū)的間隔太小,應(yīng)用層不能在兩次消息中間取走上一條消息,那么下次讀取的時(shí)候,就勢(shì)必會(huì)把兩包消息同時(shí)讀出來,這也會(huì)導(dǎo)致粘包。
而且這個(gè)情況并不能通過讓發(fā)送端在時(shí)間上均勻發(fā)包來避免,因?yàn)榫W(wǎng)絡(luò)不穩(wěn)定情況的存在,即使是時(shí)間上均勻發(fā)送的數(shù)據(jù)包,在接收端看來也可能是隨機(jī)出現(xiàn)的。
如何規(guī)避粘包的負(fù)面影響?
根據(jù)以上分析,我們不難發(fā)現(xiàn),想要杜絕粘包的問題出現(xiàn),基本上是不可能的。即使發(fā)送端和接收端都能自己控制,但是網(wǎng)絡(luò)傳輸?shù)倪^程也是很難控制的。
但是即使粘包的問題存在,也不影響我們大規(guī)模的使用TCP協(xié)議。因?yàn)檫@個(gè)問題在應(yīng)用層非常好處理。大致有兩種思路:1. 在信息中加入特殊的標(biāo)志作為分隔符
這樣,當(dāng)應(yīng)用層檢測(cè)到特殊的分隔符后,便知道這是一包得到開始和結(jié)束,就可以進(jìn)行分片等操作,問題便迎刃而解。不過這樣存在一些弊端。比如定義分隔符為“12345678”,那如果消息內(nèi)容里面出現(xiàn)“12345678”的字符串呢?這樣就會(huì)導(dǎo)致消息被異常的切片,導(dǎo)致接收到的消息錯(cuò)誤。但假如自己能夠控制消息的內(nèi)容,保證里面不會(huì)出現(xiàn)“12345678”的內(nèi)容,則此方法較為靈活。2. 加入信息的長(zhǎng)度根據(jù)約定好的長(zhǎng)度的字段,讀取消息長(zhǎng)度的信息,再根據(jù)消息長(zhǎng)度信息讀取消息內(nèi)容。這也是一種非常常用的方法,在很多協(xié)議中都有體現(xiàn)。
3. 添加包首部發(fā)送端給每個(gè)數(shù)據(jù)包添加包首部,首部中應(yīng)該至少包含數(shù)據(jù)包的長(zhǎng)度,這樣接收端在接收到數(shù)據(jù)后,就可以通過讀取包首部的長(zhǎng)度字段,知道每一個(gè)數(shù)據(jù)包的實(shí)際長(zhǎng)度。以上就是本期關(guān)于解決TCP粘包問題的內(nèi)容,小編碼字不易,求個(gè)點(diǎn)贊、分享、在看三連支持!我們下期見~~
-
TCP
+關(guān)注
關(guān)注
8文章
1381瀏覽量
79349
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
華納云如何解讀WinMTR的丟包率數(shù)據(jù)?
Linux網(wǎng)卡收包流程
![Linux網(wǎng)卡收<b class='flag-5'>包</b>流程](https://file1.elecfans.com/web3/M00/01/30/wKgZPGdRYs6AP8t0AAAg_WndtXo681.png)
集成電路微組裝用環(huán)氧粘接膠樹脂析出及控制研究
原來UV膠水在LED燈具粘接中有這么多用膠點(diǎn)
esp8266讀取模擬數(shù)據(jù)并記錄到eeprom,發(fā)送tcp包時(shí)無法讀取模擬如何解決?
tcp_client例程為何去掉發(fā)送后,一直接收就會(huì)容易出現(xiàn)數(shù)據(jù)粘包呢?
lwip tcp丟包的原因?
軟包電池和硬包電池的區(qū)別有哪些呢?
儲(chǔ)能電池包ccs結(jié)構(gòu)介紹 儲(chǔ)能電池包的結(jié)構(gòu)原理是什么?
鋰電池軟包和硬包哪個(gè)好
電池包擠壓針刺試驗(yàn)機(jī)的測(cè)試結(jié)果如何解讀?
![電池<b class='flag-5'>包</b>擠壓針刺試驗(yàn)機(jī)的測(cè)試結(jié)果如<b class='flag-5'>何解</b>讀?](https://file1.elecfans.com/web2/M00/D6/EF/wKgaomYnHOGAbu6hAABXevoPcf4078.png)
技術(shù)分享 | 芯片粘接空洞的超聲檢測(cè)
![技術(shù)分享 | 芯片<b class='flag-5'>粘</b>接空洞的超聲檢測(cè)](https://file.elecfans.com/web2/M00/32/8E/pYYBAGIYTSWAcimeAAB_E_xbEBU241.png)
評(píng)論