TCP以流的形式進行數據傳輸,上層的應用協議為了對消息進行劃分,往往采用如下的4種方式。
(1)消息長度固定,累計讀到長度總和為定長len的報文后,就認為讀取到了一個完整的消息;然后重新開始讀取下一個“完整”的數據包;
(2)將回車換行符作為消息結束符,如ftp協議;
(3)將特殊的分隔符作為消息的結束標識,回車換行符j是一種特殊的分隔符;
(4)通過在消息頭中定義的長度字段表示消息的總長度;
Netty對以上4種應用做了抽象,提供了4種解碼器,有了解碼器,碼農們不用考慮TCP的粘包、拆包的問題了。
LineBasedFrameDecoder:依次編譯bytebuf中的可讀字符,判斷看是否有“/n”或者“/r/n”,如果有,就以此位置為結束位置,從可讀索引到結束位置區間的字節就組成了一行。它是以換行符為結束標志的解碼器,支持攜帶結束符或者不攜帶結束符兩種解碼方式,同時支持單行的最大長度。如果連續讀取到最大長度后,仍然沒有發現換行符,就會拋出異常,同時忽略掉之前讀到的異常碼流。(具體例子介紹在《Netty(三)TCP粘包拆包處理》)
FixedLengthFrameDecoder:是固定長度解碼器,它能按照指定的長度對消息進行自動解碼,開發者不需要考慮TCP的粘包等問題。利用FixedLengthFrameDecoder解碼,無論一次性接收到多少的數據,他都會按照構造函數中設置的長度進行解碼;如果是半包消息,FixedLengthFrameDecoder會緩存半包消息并等待下一個包,到達后進行拼包,直到讀取完整的包。
DelimiterBasedFrameDecoder:是自定義的分隔符解碼,構造函數的第一個參數表示單個消息的最大長度,當達到該長度后仍然沒有查到分隔符,就拋出TooLongFrameException異常,防止由于異常碼流缺失分隔符導致的內存溢出。
源碼在src/main/java/Decoder下,分為客戶端和服務端,他們的代碼基本和Netty入門章節的代碼類似,只是增加了解碼器。
GitHub地址:https://github.com/orange1438/Netty_Course
新聞熱點
疑難解答