1.OSI&TCP/IP參考模型
2.TCP粘包/拆包
? ? ? ?TCP是一個(gè)面向連接的字節(jié)流數(shù)據(jù)傳輸控制協(xié)議此蜈,沒有自動(dòng)插入記錄標(biāo)志或消息邊界试和,TCP并不解讀字節(jié)流里的字節(jié)內(nèi)容,而是將數(shù)據(jù)放入接收緩沖區(qū);
1)粘包/拆包現(xiàn)象
? ? ? ?假設(shè)發(fā)送端向接收端連續(xù)發(fā)送了2個(gè)數(shù)據(jù)報(bào):
-
無粘包/拆包:接收端分兩次讀取松忍,正常獲得兩個(gè)獨(dú)立的數(shù)據(jù)包跋理;
-
粘包:接收端只接受到一個(gè)數(shù)據(jù)包择克,由于TCP不會(huì)出現(xiàn)丟包,所以該數(shù)據(jù)包包含了發(fā)送端發(fā)送的2個(gè)數(shù)據(jù)包信息前普;
-
拆包:接收端接受到了2個(gè)數(shù)據(jù)包肚邢,但是這兩個(gè)數(shù)據(jù)包要么不完整,要么多出了另一個(gè)數(shù)據(jù)包的部分信息拭卿;
(上述圖片來源于https://blog.csdn.net/scythe666/article/details/51996268)
2)為什么會(huì)出現(xiàn)粘包/拆包道偷? 待發(fā)送的數(shù)據(jù)大于TCP發(fā)送緩沖區(qū)可用空間大小,將會(huì)發(fā)生拆包记劈;
待發(fā)送數(shù)據(jù)大于MSS(最大報(bào)文長度)勺鸦,即TCP報(bào)文長度-TCP頭部長度>MSS,TCP將在傳輸前進(jìn)行拆包目木;
待發(fā)送數(shù)據(jù)小于SMSS换途,且存在在傳數(shù)據(jù)(已發(fā)送未確認(rèn)),由于Nagle算法刽射,這些小的報(bào)文段不能被發(fā)送军拟,直到所有在傳數(shù)據(jù)都收到ACK后,TCP將收集這些小的報(bào)文段誓禁,將其整合到一個(gè)報(bào)文段中發(fā)送懈息,從而發(fā)送粘包;
接收端的應(yīng)用層沒有及時(shí)讀取接收緩沖區(qū)中的數(shù)據(jù)摹恰,發(fā)生粘包辫继;
3)怎么解決粘包/拆包?
- 使用TCP_NODELAY關(guān)閉Nagle算法俗慈,解決由于發(fā)送端Nagke算法導(dǎo)致的粘包姑宽;
- 消息定長,空格補(bǔ)位闺阱;
- 設(shè)置邊界炮车,添加特殊符號(hào),如包尾添加回車換行符(FTP);
- 將消息分為消息頭和消息體瘦穆,消息頭中包含消息長度纪隙;
Netty提供了不同方法來處理粘包和拆包:
- DelimiterBasedFrameDecoder 基于設(shè)置消息邊界方式進(jìn)行粘包/拆包處理;
- FixedLengthFrameDecoder 基于固體長度消息進(jìn)行粘包/拆包處理扛或;
- LengthFieldBasedFrameDecoder 基于消息頭指定消息長度進(jìn)行粘包/拆包處理绵咱;
- LineBasedFrameDecoder 基于換行符進(jìn)行粘包/拆包處理。
工作原理是:依次遍歷ByteBuf中的可讀字節(jié)告喊,判斷是否有"/n"或者"/r/n"麸拄,如果有,就以此位置為結(jié)束位置黔姜,從可讀索引到結(jié)束位置區(qū)間的字節(jié)就組成了一行拢切。是以換行符為結(jié)束標(biāo)志的解碼器,支持?jǐn)y帶結(jié)束符或者不攜帶結(jié)束符兩種解碼方式秆吵,同時(shí)支持配置單行最大長度淮椰,若連續(xù)讀取到最大長度仍然沒有發(fā)現(xiàn)換行符,則拋出異常纳寂;