<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] 1. Netty 在內部使用了回調來處理事件;當一個回調被觸發時,相關的事件可以被一個 interfaceChannelHandler 的實現處理。當一個新的連接已經被建立時,ChannelHandler 的 channelActive()回調方法將會被調用,并將打印出一條信息。 2. 所有的 Netty 服務器都需要以下兩部分。 * 至少一個 ChannelHandler—該組件實現了服務器對從客戶端接收的數據的處理,即 它的業務邏輯。 * 引導—這是配置服務器的啟動代碼。至少,它會將服務器綁定到它要監聽連接請求的 端口上。 在本小節的剩下部分,我們將描述 Echo 服務器的業務邏輯以及引導代碼。 3. 每個 Channel 都擁有一個與之相關聯的 **ChannelPipeline**,其持有一個 ChannelHandler 的實例鏈。也就是說一個pipeline上有多個channel,這些channel是串聯起來的,并且上一個channel的結果會傳遞到下一個channel。 ![](https://box.kancloud.cn/6a729eb2adb0e1ad312191a225300e1d_700x297.png) :-: 圖一 ## 1. 引導(Bootstrap) ### 1.1 ServerBootstrap 服務端啟動引導類,設置netty服務端啟動參數 兩種類型的引導: > 1. 一種用于客戶端(簡單地稱為 Bootstrap) > 2. 而另一種( ServerBootstrap)用于服務器。 > ## 2. EventLoopGroup EventLoop 定義了 Netty 的核心抽象, 用于處理連接的生命周期中所發生的事件。 ![](https://box.kancloud.cn/792969533c082e041c425c17efa20952_833x641.png) :-: 圖二 1. 一個 EventLoopGroup 包含一個或者多個 EventLoop; 2. 一個 EventLoop 在它的生命周期內只和一個 Thread 綁定; 3. 所有由 EventLoop 處理的 I/O 事件都將在它專有的 Thread 上被處理; 4. 一個 Channel 在它的生命周期內只注冊于一個 EventLoop; 5. 一個 EventLoop 可能會被分配給一個或多個 Channel。 注意,在這種設計中, 一個給定 Channel 的 I/O 操作都是由相同的 Thread 執行的, 實際上消除了對于同步的需要。 ## 1. channel 基本的 I/O 操作( bind()、 connect()、 read()和 write())依賴于底層網絡傳輸所提供的原語。在基于 Java 的網絡編程中,其基本的構造是 class Socket。 Netty 的 Channel 接口所提供的 API,大大地降低了直接使用 Socket 類的復雜性。此外, Channel 也是擁有許多預定義的、專門化實現的廣泛類層次結構的根,下面是一個簡短的部分清單: 每個channel都對應一個物理連接,每個連接都有自己獨立的TCP參數。 > 1. EmbeddedChannel; > 2. LocalServerChannel; > 3. NioDatagramChannel; > 4. NioSctpChannel; > 5. NioSocketChannel。 1. channel和childHandler netty服務是父級的、初始的channel線程,負責監聽整個服務。后接入的鏈接都會開啟一個channel,成為childChannel。 在基類AbstractBootstrap有handler方法,目的是添加一個handler,監聽Bootstrap的動作,客戶端的Bootstrap中,繼承了這一點。 在服務端的ServerBootstrap中增加了一個方法childHandler,它的目的是添加handler,用來監聽已經連接的客戶端的Channel的動作和狀態。 handler在初始化時就會執行,而childHandler會在客戶端成功connect后才執行,這是兩者的區別。 ![](https://box.kancloud.cn/1e3870519ff613cb8b95dc3538b32f59_859x272.png) 如圖所示, 每個 Channel 都將會被分配一個 ChannelPipeline 和 ChannelConfig。ChannelConfig 包含了該 Channel 的所有配置設置, 并且支持熱更新。由于特定的傳輸可能具有獨特的設置, 所以它可能會實現一個 ChannelConfig 的子類型。 Netty 的 Channel 實現是線程安全的,因此你可以存儲一個到 Channel 的引用,并且每當你需要向遠程節點寫數據時, 都可以使用它, 即使當時許多線程都在使用它。 ## ChannelHandler 實際的數據業務處理邏輯 1. 針對不同類型的事件來調用 ChannelHandler; 2. 應用程序通過實現或者擴展 ChannelHandler 來掛鉤到事件的生命周期,并且提供自定義的應用程序邏輯; 3. 在架構上, ChannelHandler 有助于保持業務邏輯與網絡處理代碼的分離。這簡化了開發過程,因為代碼必須不斷地演化以響應不斷變化的需求。 4. ChannelInitializer。這是關鍵。當一個新的連接被接受時,一個新的子 Channel 將會被創建,而 ChannelInitializer 將會把一個你的EchoServerHandler 的實例添加到該 Channel 的 ChannelPipeline 中。正如我們之前所 解釋的,這個 ChannelHandler 將會收到有關入站消息的通知 ### 方法 #### channelActive() 當有連接建立時調用 #### channelRead(ChannelHandlerContext ctx, Object msg) 1. 每當接收數據時,都會調用這個方法。 2. 需要注意的是,由服務器發送的消息可能會被分塊接收。 也就是說,如果服務器發送了 5 字節, 那么不能保證這 5 字節會被一次性接收。 即使是對于這么少量的數據, channelRead0()方法也可能會被調用兩次,第一次使用一個持有 3 字節的 ByteBuf( Netty 的字節容器),第二次使用一個持有 2 字節的 ByteBuf。作為一個面向流的協議, TCP 保證了字節數組將會按照服務器發送它們的順序被接收。 ## ChannelFuture Netty 中所有的 I/O 操作都是異步的。因為一個操作可能不會立即返回,所以我們需要一種用于在之后的某個時間點確定其結果的方法。為此, Netty 提供了ChannelFuture 接口,其 addListener()方法注冊了一個 ChannelFutureListener,以便在某個操作完成時(無論是否成功)得到通知。 ## ChannelPipeline ### 與ChannelHandler的關系 1. 當ChannelHandler 被添加到ChannelPipeline 時,它將會被分配一個ChannelHandlerContext,其代表ChannelHandler 和 ChannelPipeline 之間的綁定。雖然這個對象可以被用于獲取底層的 Channel,但是它主要還是被用于寫出站數據。 2. **ChannelPipeline 提供了 ChannelHandler 鏈的容器**,并定義了用于在該鏈上傳播入站和出站事件流的 API。當 Channel 被創建時, 它會被自動地分配到它專屬的 ChannelPipeline。Handler安裝過程如下: > 1. 一個ChannelInitializer的實現被注冊到了ServerBootstrap中 > 2. 當 ChannelInitializer.initChannel()方法被調用時, ChannelInitializer將在 ChannelPipeline 中安裝一組自定義的 ChannelHandler > 3. ChannelInitializer 將它自己從 ChannelPipeline 中移除 ### 入、出站 ![](https://box.kancloud.cn/55c6e14a3afd8613a5cd9052ca4c6984_858x209.png) :-: 圖三 數據、事件入站出站示意圖 從一個客戶端應用程序的角度來看,如果事件的運動方向是從客戶端到服務器端, 那么我們稱這些事件為出站的,反之則稱為入站的。 ~~~ ChannelInboundHandler :入站Handler ChannelOutboundHandler :出站Handler ~~~ #### 入站 如果一個消息或者任何其他的入站事件被讀取, 那么它會從 ChannelPipeline 的頭部開始流動,并被傳遞給第一個 ChannelInboundHandler。這個 ChannelHandler 不一定會實際地修改數據, 具體取決于它的具體功能,在這之后,數據將會被傳遞給鏈中的下一個ChannelInboundHandler。最終,數據將會到達 ChannelPipeline 的尾端, 屆時,所有處理就都結束了-**數據處理是一個Handler接著一個Handler執行的。** #### 出站 數據的出站運動(即正在被寫的數據)在概念上也是一樣的。在這種情況下,數據將從ChannelOutboundHandler 鏈的尾端開始流動,直到它到達鏈的頭部為止。在這之后,出站數據將會到達網絡傳輸層,這里顯示為 Socket。通常情況下,這將觸發一個寫操作。 ## ChannelHandlerContext 1. 通過使用作為參數傳遞到每個方法的 ChannelHandlerContext,事件可以被傳遞給當前ChannelHandler 鏈中的下一個 ChannelHandler。 2. 因為你有時會忽略那些不感興趣的事件,所以 Netty提供了抽象基類 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter。通過調用 ChannelHandlerContext 上的對應方法,每個都提供了簡單地將事件傳遞給下一個 ChannelHandler的方法的實現。隨后, 你可以通過重寫你所感興趣的那些方法來擴展這些類。 如果將兩個類別的 ChannelHandler都混合添加到同一個 ChannelPipeline 中會發生什么。 雖然 ChannelInboundHandle 和ChannelOutboundHandle 都擴展自 ChannelHandler,但是 Netty 能區分 ChannelInboundHandler 實現和 ChannelOutboundHandler 實現,并確保數據只會在具有相同定向類型的兩個 ChannelHandler 之間傳遞. ### netty發送數據方式 在 Netty 中, 有兩種發送消息的方式: 1. 直接寫到 Channel 中,消息從ChannelPipeline 的尾端開始流動 2. 寫到和 ChannelHandler相關聯的ChannelHandlerContext對象中,消息從 ChannelPipeline 中的下一個 ChannelHandler 開始流動。 ### 區別 ![](https://box.kancloud.cn/94a08bb290751e92aa1c80bf3bd9edbe_963x123.png) 1. ServerBootstrap 將綁定到一個端口,因為服務器必須要監聽連接, 而 Bootstrap 則是由想要連接到遠程節點的客戶端應用程序所使用的。 2. 引導一個客戶端只需要一個 EventLoopGroup,但是一個ServerBootstrap 則需要兩個(也可以是同一個實例)。 **為什么ServerBootstrap需要兩個EventLoopGroup?** 因為服務器需要兩組不同的 Channel。第一組將只包含一個 ServerChannel,代表服務器自身的已綁定到某個本地端口的在監聽的套接字。 而第二組將包含所有已創建的用來處理傳入客戶端連接( 對于每個服務器已經接受的連接都有一個) 的 Channel。如下圖: ![](https://box.kancloud.cn/f94e81a67fb7a4c5e0f64428deb9676f_906x393.png) 與 ServerChannel 相關聯的 EventLoopGroup 將分配一個負責為傳入連接請求創建Channel的EventLoop。一旦連接被接受,第二個EventLoopGroup就會給它的Channel分配一個EventLoop。 實際上, ServerBootstrap 類也可以只使用一個 EventLoopGroup,此時其將在兩個場景下共用同一個 EventLoopGroup。 ## 傳輸 ![](https://box.kancloud.cn/a42b3c16f9354a6efe06a7df0421d099_880x182.png) ![](https://box.kancloud.cn/ae083cf6b4019846fd1b52243acaff1d_876x212.png) ### 1 非阻塞I/O 選擇器背后的基本概念是充當一個注冊表,在那里你將可以請求在 Channel 的狀態發生變化時得到通知并觸發動作。可能的狀態變化有: > 1. 新的 Channel 已被接受并且就緒; > 2. Channel 連接已經完成; > 3. Channel 有已經就緒的可供讀取的數據; > 4. Channel 可用于寫數據。 對應selector模式 ![](https://box.kancloud.cn/9b78b20031c226efcd17d1753f7e0fdb_851x235.png) ## ByteBuf——Netty 的數據容器 ### 讀寫索引 ## 異常處理 ## channel生命周期 ![](https://box.kancloud.cn/089a7096c9703f94c54276a705e4f88a_1278x369.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看