[toc]
1.什么是TCP粘包和半包常空?為什么會出現粘包和半包沽一?
粘包:
粘包半包 混合雙打:
首先TCP是可靠有序的颜说。tcp序列號確認號儒将,失敗重傳機制等都保證了他不會出現亂序和丟失報文的現象。但是因為TCP是面向字節(jié)流的鹦付,消息無邊界昆禽,所以面臨這樣的問題蝗蛙。
2.什么情況會出現粘包和半包?
上面也解釋了一部分醉鳖,下面具體看什么情況:
粘包
- 發(fā)送方每次寫入的數據 < 套接字緩存區(qū)大小
- 接收方接受套接字緩沖區(qū)不夠及時
半包
- 發(fā)送方每次寫入數據 > 套接字緩沖區(qū)大小
- 發(fā)送的數據大于協議MTU(最大傳輸單元捡硅,必須拆包)
3.如何解決粘包和半包?
上面講盗棵,出現粘包和半包的原因就是TCP流式傳輸壮韭,消息無邊界,找出消息邊界解決問題纹因,(簡單的來說喷屋,就是讓接收端知道一次需要read幾個字節(jié)是一段話就ok)
長 = 長鏈接,每次數據封裝為幀
方式\比較 | 找到消息邊界方式 | 優(yōu)點 | 缺點 |
---|---|---|---|
短連接/一個請求一個短連接 | 連接釋放之前的信息為傳輸消息 | 簡單 | 效率低下 |
長(固定長度) | 讀取固定長度 | 簡單 | 可能會空間浪費 |
長(分隔符) | 分隔符 | 簡單 | 內容中有分隔符需要轉義 |
長(固定長度字段存內容的長度消息) | 協議頭中制定消息體的長度 | 優(yōu)秀 上面問題都不存在 | 長度有限制(表示長度的這個幾個字節(jié)本身能表達的數字是有限的) |
長(其他方式) | 每種都不同瞭恰,列如json可以看{}是否成對了 |
==協議 = 協議頭[定長] + (Object)序列化后的消息體==
一般我們實現通心層都需要定義一個通信層協議屯曹,協議頭固定長度,協議頭中包含了消息體的長度。這樣我們接收端不就知道了消息界限了嗎恶耽。
- 我們把 “找到消息邊界方式” 視為第一層解碼
- “消息體反序列化”視為第二層解碼
4.Netty中如何實現密任?
- 我們把 “找到消息邊界方式” 視為第一層解碼
- “消息體反序列化”視為第二層解碼
Netty中為什么不合二為一?
- 沒有分層偷俭,不夠清晰
- 耦合性高浪讳,不容易切換方案
第一次解碼器
ByteToMessageDecoder
- 原始數據量->用戶數據
方式\支持 | 解碼 | 編碼 |
---|---|---|
固定長度 | FixedLengthFrameDecoder | 不內置 |
分隔符 | DelimiterBaseFrameDecoder | 太簡單不內置 |
固定長度字段,存內容的長度信息 | LengthFieldBaseFrameDecoder | LengthFieldPrepender |
第二次解碼器
MessageToMessageDecoder<T>
- 用戶數據->java Object
如何選擇社搅?
- 空間大凶ふ(根據數據量變)
- 編解碼速度(根據數據量變)
- 可讀性
- 多語言支持