初識Netty
我們已經了解了Socket通信/IO/NIO/AIO編程,對於通信模型已經有了一個初步的認識,其實我們之前所學習的僅僅是一個模型,如果想把這些真正的用於實際工作中去,其實我們之前所學習的僅僅是一個模型,如果想把這些真正的用於實際工作中去,那麽還需要不斷的完善、擴展和優化。比如很經典的TCP讀包寫包問題,或者是數據接收的大小,實際的用心讀取與應答的處理邏輯等一些細節問題需要我們認真的去思考,而這些我們都需要大量的時間和經歷,以及豐富的經驗。所以想學好socket通信不是件容易的事情,那麽現在,我們就要學習一門新的技術Netty,我們為什麽選擇Netty,原因無他,簡單!我們再也不必去編寫復雜的代碼邏輯去實現通信,我們再也不需要去考慮性能為題,不需要考慮編碼問題,半包讀寫問題等,這些強大的Netty已經幫我們實現好了,我們只需要使用即可。
Netty是也就最留下的NIO框架,他的健壯性、功能、性能、可定制性和可擴展性在同類框架都是首屈一指的。它已經得到成百上千的商業/商用項目驗證,如Hadoop的RPC框架Avro、以及我們之後學習的JMS框架,強大的RocketMQ、還要主流的分布式通信框架Dubbox等等。
Netty是基於Java NIO的網絡應用框架。
Netty是一個NIO client-server(客戶端服務器)框架,使用Netty可以快速開發網絡應用,例如服務器和客戶端協議。Netty提供了一種新的方式來開發網絡應用程序,這種新的方式使得它很容易使用和有很強的擴展性。Netty的內部實現是很復雜的,但是Netty提供了簡單易用的api從網絡處理代碼中解耦業務邏輯。Netty是完全基於NIO實現的,所以整個Netty都是異步的。
網絡應用程序通常需要有較高的可擴展性,無論是Netty還是其他的基於Java NIO的框架,都會提供可擴展性的解決方案。Netty中一個關鍵組成部分是它的異步特性,下面將討論同步(阻塞)和異步(非阻塞)的IO來說明為什麽使用異步代碼來解決擴展性問題以及如何使用異步。
Netty架構組成
Netty特性
下面開始看一個入門代碼,在用Netty之前,回顧下NIO通信步驟:
1.創建ServerSocketChannel,為它配置非阻塞模式
2.綁定監聽,配置TCP參數,錄入bacllog大小等
3.創建一個獨立的IO線程,用戶輪詢多路復用器Selector
4.創建Selector,將之前創建的ServerSocketChannel註冊到Selector上,並設置監聽標識位
5.啟動IO線程,在循環體中執行Selector.select()方法,輪詢就緒的通道
6.當輪詢到了處於就緒的通道時,需要進行判斷操作位,如果是ACCEPT狀態,說明是新的客戶端接入,則調用accept方法接受新的客戶端。
7.設置新接入客戶端的一些參數,如非阻塞、並將其通道繼續註冊到Selector之中,設置監聽標識位等
8.如果輪詢的通道操作位是READ,則進行讀取,構造Buffer對象等
9.更細節的還要數據沒法送完成繼續發送的問題。。。
一個簡單的NIO服務器端程序,就是如此的復制,下面看一下Netty完成這件事情需要的步驟:
Netty實現通信的步驟:
1.創建兩個NIO線程組,一個專門用於網絡事件處理(接受客戶端的連接),另一個則進行網絡通信讀寫。
2.創建一個ServerBootstrap對象,配置Netty的一系列參數,例如接受傳出數據的緩存大小等等。
3.創建一個實際處理數據的類Channellnitializer,進行初始化的準備工作,比如設置接受傳出數據的字符集、格式、已經實際處理數據的接口。
4.綁定端口,執行同步阻塞方法等待服務器端啟動即可。
就這麽4個步驟,下面看一個實現的demo:
上面是Server端的代碼,主要是設置一下配置,具體的代碼的實現等,都是在ServerHandler裏面執行。下面看一下ServerHandler的代碼:
這裏是ServerHandler的代碼,要註意的是在調用writeAndFlush()方法時,會自動釋放上一次的流,不用調用ReferenceCountUtil.release(msg);這個方法,下面看一下Client端的代碼:
需要註意的是,這邊的通道使用的是NIOSocketChannel對象。在初始化的時候,去調用ClientHandler, 下面看一下ClientHandler
看一下運行結果:
看一下server端:
接收到Client發送的777,然後server回送一個響應
看一下Client端
接收到了Server端的響應,打印了相應的數據
強烈推薦去http://ifeve.com/netty5-user-guide/查看一下用戶指南
初識Netty