基於I/O操做(例如:bind()、connect()、read()和write())依賴於底層網絡傳輸提供的原語。在基於Java的網絡編程中,其基本構造爲類Socket。
Netty的Channel接口所提供的API,大大下降了直接使用Socket類的複雜性。
Channel擁有許多預約義的、專門化實現的普遍類層次結構的根,以下:編程
EventLoop定義了Netty的核心抽象,用於處理鏈接的生命週期中所發生的事件。服務器
Channel、EventLoop、Thread、EventLoopGroup關係示意圖網絡
一個給定Channel的I/O操做都是由相同的Thread執行的,實際上消除了對於同步的須要多線程
Netty中全部的I/O操做都是異步的,由於一個操做不可能當即返回,因此咱們須要一種用於在以後的某個時間點肯定其結果的方法。
所以Netty提供了ChannelFuture接口,其addListener()方法註冊了一個ChannelFutureListener,以便在某個操做完成時(不管是否成功)獲得通知。併發
主要用來管理數據流已經執行應用程序處理邏輯異步
ChannelHandler充當了全部處理入站和出站數據的應用程序邏輯的容器。
ChannelHandler可專門用於幾乎任何類型的動做,例如將數據從一種格式轉換爲另一種格式,或者處理轉換過程當中所拋出的異常。
ChannelHandler能夠用來接收入站事件和數據,隨後使用應用程序的業務邏輯進行處理。當你的客戶端須要發送響應時,能夠從ChannelInboundhandler沖刷數據。
你的應用程序的業務邏輯一般駐留在一個或者多個ChannelInboundHandler中。oop
ChannelPipeline是ChannelHandler鏈的容器,並定義用於在該鏈上傳播入站和出站事件流的API。當Channel被建立時,它會被自動地分配到它專屬的ChannelPipeline。
編碼
ChannelHandler被安裝到ChannelPipeline中過程以下:spa
ChannelHandler可讓事件流經ChannelPipeline,它們是在應用程序的初始化或者引導階段被安裝的。這些對象接收事件、執行它們所實現的處理邏輯,並將數據傳遞給鏈中的下一個ChannelHandler。它們的執行順序是由它們被添加的順序決定的。
ChannelPipeline是這些ChannelHandler的編排順序。線程
入站和出站ChannelHandler能夠被安裝到同一個ChannelPipeline中。若是一個消息或者任何其餘的入站事件被讀取,那麼它會從ChannelPipeline的頭部開始流動,並被傳遞給第一個ChannelInboundHandler。這個ChannelHandler不必定會實際地修改數據,具體取決於它的具體功能,在這以後,數據將會被傳遞給鏈中的下一個ChannelInboundHandler。最終,數據會到達ChannelPipeline的尾端,屆時,全部處理就都結束了。
出站數據將會從ChannelOutboundHandler鏈的尾端開始流動,直到它到達鏈的頭部爲止。在這以後,出站數據將會到達網絡傳輸層。
經過使用做爲參數傳遞到每一個方法的ChannelHandlerContext,事件能夠被傳遞給當前ChannelPipeLine中的下一個ChannelHandler。由於用戶並非關心全部的事件,所以Netty提供了抽象類ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。經過調用ChannelHandlerContext上的對應的方法,均可以簡單地將事件傳遞給下一個ChannelHandler的方法的實現。
當ChannelHandler被添加到ChannelPipeline時,它將會被分配一個ChannelHandlerContext,它表明了Channel和ChannelPipeline之間的綁定。雖然這個對象能夠被用於獲取底層的Channel,可是它主要仍是被用於出站寫數據。
在Netty中,有兩種發送消息的方式:
雖然ChannelInboundHandler和ChannelOutboundHandler都擴展自ChannelHandler,可是Netty能夠區分兩種Handler的實現,並確保數據只會在具備相同定向類型的兩個ChannelHandler之間傳遞。
不一樣類型的ChannelHandler各自的功能主要取決於它們的超類。Netty以適配器類的形式提供了大量默認的ChannelHandler實現,其旨在簡化應用程序處理邏輯的開發過程。
這些適配器類能夠自動將事件轉發到ChannelPipeline中的下一個ChannelHandler,因此你能夠只重寫那些你想要特殊處理的方法和事件。
有一些適配器類能夠將編寫自定義的ChannelHanlder所須要的努力降到最低限度,由於它們提供了定義在對應接口中的全部方法的默認實現。
經常使用的適配器類有:
全部由Netty提供的編碼/解碼適配器類都實現了ChannelOutboundHandler或者ChannelInboundHandler接口。
對於入站數據,channelRead方法已經被重寫了。對於每個從入站Channel讀取的消息,這個方法都會被調用。隨後,它將調用由預置解碼器提供的decode()方法,並將已解碼的字節轉發給ChannelPipeline中的下一個ChannelHandler,出站相反。
最多見的一個狀況,你的應用程序會利用一個ChannelHandler來接受解碼消息,並對該數據應用業務邏輯。要建立一個這樣的ChannelHandler,只須要擴展SimpleChannelInboundHandler<T>,其中<T>是你要處理的消息的Java類型。
在這個ChannelHandler中,你將須要重寫基類的一個或者多個方法,而且獲取一個ChannelHandlerContext的引用,這個引用將做爲參數傳遞給ChannelHandler的全部方法。
在這種類型的ChannelHandler中,最重要的方法是channelRead0(ChannelHandlerContext , T)。除了要求不阻塞當前的I/O線程以外,其具體實現徹底取決於你。
Netty的引導類爲應用程序的網絡層配置提供了容器。
Bootstrap類比較
類別 | Bootstrap | ServerBootstrap |
---|---|---|
網絡編程中的做用 | 鏈接到遠程主機和端口 | 綁定到一個本地端口 |
EventLoopGroup的數目 | 1 | 2 |
區別分析:
3.與ServerChannel相關聯的EventLoopGroup將分配一個負責爲傳入鏈接請求建立Channel的EventLoop。一旦鏈接被接受,第二個EventLoopGroup就會給它的Channel分配一個EventLoop。
具備兩個EventLoopGroup的服務器