- 在一個項目中织盼,要在TCP連接的客戶端和服務(wù)器之間發(fā)送json形式的數(shù)據(jù)危彩。遇到了一個問題茶鉴,有時候數(shù)據(jù)發(fā)送端連續(xù)多次調(diào)用send()函數(shù)發(fā)送多條json字符串時,接收端用recv()函數(shù)接收一條數(shù)據(jù)是一個組合多條json的大字符串灭返,并不是期望的收到多條分割開的json字符串盗迟。這就是TCP的粘包問題。
- 這就導致在使用cJSON_Parse()函數(shù)對json字符串進行解析時熙含,只能解析出第一條完整的json罚缕,而后面的就丟棄了。這種情況對于每條json是一條命令來說怎静,是很糟糕的邮弹。
- 其實這種每條json是一個命令的業(yè)務(wù)需求,使用UDP來發(fā)送數(shù)據(jù)蚓聘,就不會發(fā)生粘包問題腌乡。UDP是數(shù)據(jù)報傳輸協(xié)議,顧名思義其就是每次發(fā)送一個數(shù)據(jù)報夜牡,不會進行多條的封裝拼湊再集體發(fā)送与纽。
在socket網(wǎng)絡(luò)程序中,TCP和UDP分別是面向連接和非面向連接的塘装。因此TCP的socket編程急迂,收發(fā)兩端(客戶端和服務(wù)器端)都要有成對的socket,因此蹦肴,發(fā)送端為了將多個發(fā)往接收端的包僚碎,更有效的發(fā)到對方,使用了優(yōu)化方法(Nagle算法)阴幌,將多次間隔較小勺阐、數(shù)據(jù)量小的數(shù)據(jù),合并成一個大的數(shù)據(jù)塊矛双,然后進行封包渊抽。這樣,接收端背零,就難于分辨出來了腰吟,必須自己提供科學的拆包機制无埃。
對于UDP徙瓶,不會使用塊的合并優(yōu)化算法,這樣嫉称,實際上目前認為侦镇,是由于UDP支持的是一對多的模式,所以接收端的skbuff(套接字緩沖區(qū))采用了鏈式結(jié)構(gòu)來記錄每一個到達的UDP包织阅,在每個UDP包中就有了消息頭(消息來源地址壳繁,端口等信息),這樣,對于接收端來說闹炉,就容易進行區(qū)分處理了蒿赢。所以UDP不會出現(xiàn)粘包問題。
https://www.cnblogs.com/kex1n/p/6502002.html
TCP通信粘包問題分析和解決(全)
====================================================================
TCP的Nagle算法和延遲ACK
- Nagle算法的操作過程請參看Wiki渣触,它減少了大量小包的發(fā)送羡棵,實際上就是基于小包的停-等協(xié)議。在等待已經(jīng)發(fā)出的包被確認之前嗅钻,發(fā)送端利用這段時間可以積累應(yīng)用下來的數(shù)據(jù)皂冰,使其大小趨向于增加。這是避免糊涂窗口綜合癥的一種有效方法养篓,請注意秃流,糊涂窗口指的是接收端的糊涂,而不是發(fā)送端的糊涂柳弄,接收端不管三七二十一得通告自己的接收窗口大小舶胀,絲毫不管這會在發(fā)送端產(chǎn)生大量小包。然而發(fā)送端可以不糊涂碧注,你通告你的峻贮,我就是不發(fā),你糊涂我不糊涂应闯,你不斷通告很小的數(shù)值纤控,我不予理睬,我有自己的方法碉纺,直到收到已經(jīng)發(fā)出包的ACK才會繼續(xù)發(fā)送船万,這就是Nagle算法的糊涂抵制方案。
- 治療糊涂窗口綜合癥有兩種方式骨田,一種是“你糊涂我不糊涂”的方式耿导,即上述的Nagle算法的方式,另外一種是“治療接收端的糊涂”的方式态贤,其中一種機制是延遲ACK(還有其它機制舱呻,比如不發(fā)送小窗口通告等)∮破可以看出箱吕,這兩種方式中都在試圖減少包的發(fā)送量,二者殊途同歸的解決了同一問題柿冲,對于發(fā)送方而言茬高,不理會接收端的小窗口通告等于說不馬上發(fā)送小包,小包得以有時間積累成大包假抄,對于接收方而言怎栽,延遲ACK可以拖延ACK發(fā)送時間丽猬,進而延遲窗口通告,在這段時間內(nèi)熏瞄,接收窗口有機會進一步(由于應(yīng)用程序處理)放大脚祟。單獨理解這兩種方式都是簡單的,但是一旦它們混在一起使用强饮,情況就會非常不幸愚铡!因為...
- Nagle算法和延遲ACK作用在方向相反的數(shù)據(jù)包和針對該數(shù)據(jù)包的確認包上,因此它們的作用力會相悖胡陪,結(jié)果就是誰也不能發(fā)包沥寥。就像一根繩子上拴兩只青蛙一樣,被對方牽制誰也跑不了柠座!關(guān)鍵點在于邑雅,小包的發(fā)送依賴于ACK,然而延遲ACK阻止了ACK的即時發(fā)送妈经,形成了僵持狀態(tài)淮野。本來只是為了減少網(wǎng)絡(luò)上小包的數(shù)量(再次強調(diào)Nagle算法以及延遲ACK的目的,注意吹泡,糊涂窗口綜合癥只是網(wǎng)絡(luò)上小包泛濫的原因之一骤星!),卻人為引入了大量的延遲爆哑!
- 此處有一個通用的解釋洞难,Nagle算法的小包發(fā)送依賴于接收端對小包得快速確認,因此接收端對待ACK而言揭朝,應(yīng)該朝著延遲ACK相反俄方向用力队贱,即快速ACK;相對的潭袱,如果在接收端啟用了延遲ACK柱嫌,發(fā)送端就應(yīng)該不斷發(fā)送數(shù)據(jù)包,不管是大包還是小包(不考慮稍帶ACK的影響)屯换,因為發(fā)送端已經(jīng)不能指望接收端正常ACK數(shù)據(jù)包了编丘,即發(fā)送端應(yīng)該禁掉Nagle算法。以上解釋背后的思想就是數(shù)據(jù)包和ACK包是相關(guān)的彤悔,力應(yīng)該往一個方向使嘉抓,一邊拉另一邊就要推,如果兩邊都拉蜗巧,力就會抵消掉掌眠,陷入僵持。不幸點或者說悲哀的地方在于幕屹,Nagle算法和延遲ACK機制都是“拉方案”蓝丙!劃船的人都知道,劃槳手有兩種座位布局望拖,要么超同一個方向渺尘,要么面朝不同的方向,后者和TCP數(shù)據(jù)包和ACK很類似说敏,要想船往前走鸥跟,必須朝一個方向劃,雖然他們面朝相反的方向盔沫。
https://blog.csdn.net/dog250/article/details/21303679
再次談?wù)凾CP的Nagle算法與TCP_CORK選項
https://blog.csdn.net/wdscq1234/article/details/52432095
TCP-IP詳解:Nagle算法