1. 産生粘包和半包的原因
粘包産生的原因:兩個包小于緩存區的大小,傳送資料會将兩個包都放在緩沖區中一起發送,就會産生粘包的問題。
半包産生的原因:當某一個包的大于緩沖區的大小,會被發送多次,每次就收到的就是一個不完整的資料包。
常見的處理手段:
netty對不同粘包半包問題的支援類
2. 問題一:Netty如何實作編碼解碼的
檢視
ByteToMessageDecoder
,該類是解碼器的實作類,檢視其中的
channelRead
方法
1.調用了
cumulator.cumulate()
方法來實作資料包的拼接的操作
2.
callDecode()
方法解析資料包
2.1 cumulator.cumulate()方法拼接資料包
跟進源碼,發現他分為兩步:
1.如果是第一個資料包,就直接傳回該資料包
2.如果不是第一個資料包,就将最新的資料追加導員來已經接收的資料包内
2.2 callDecode()
方法解析資料包
callDecode()
核心實作方法,
decodeRemovalReentryProtection
就是
callDecode
中的核心步驟
跟進源碼
decodeRemovalReentryProtection
的源碼,其中核心方法是514行的
decode
方法,但是此方法是一個抽象方法,也就是說
ByteToMessageDecoder
隻是一個模闆類,具體的decode方法實作在子類中
于是我們檢視
ByteToMessageDecoder
的一個子類
FixedLengthFrameDecoder
,
FixedLengthFrameDecoder
是固定長度的編碼解碼方式,如果資料不足會補充空格等資料,它的decode方法如下:
1.如果我們接受到的資料小于資料幀限制的長度,那麼無法解析資料,直接傳回null
2.否則調用
readRetainedSlice
方法進行解析,
readRetainedSlice
就是将
ByteBuf
切出
frameLength
長度的資料出來
總結:Netty提供了一個
ByteToMessageDecoder
模闆類,資料包的拼接交給該類完成,但是資料包的解析
decode
是一個抽象方法,具體實作交給子類完成。
3.問題二:LengthFieldBasedFrameDecoder編碼器的實作
核心就是其中的四個參數:
1.
lengthFieldOffset
// length字段的偏移量
2.l
engthFieldLength
// legnth字段所占的長度
3.
lengthAdjustment
// 可能我們除了實際内容字段以外,還額外增加2個字段的其他資訊,lengthAdjustment=2,那麼需要讀取的資料就是length+2
4.
initialBytesToStrip
// 我們解析出來的資料是從第幾位開始的,如果我們不需要接收length字段,那麼initialBytesToStrip=2,解析出來就隻有内容部分