IO網路程式設計(三)

2021-10-06 08:54:37 字數 4195 閱讀 5451

步驟 1:建立 serverbootstrap 例項。serverbootstrap 是 netty 服務端的

啟動輔助類,它提供了一系列的方法用於設定服務端啟動相關的引數。

步 驟 2: 設 置 並 綁 定 reactor 線 程 池。netty 的 reactor 線 程 池 是

eventloopgroup,它實際就是 eventloop 的陣列。eventloop 的職責是處理所有註冊到本執行緒多路復用器 selector 上的 channel,selector 的輪詢操作由繫結的 eventloop 執行緒 run 方法驅動,在乙個迴圈體內迴圈執行。

步 驟 3: 設 置 並 綁 定 服 務 端 channel。 作 為 nio 服 務 端, 需 要 創 建serversocketchannel,netty 對 原 生 的 nio 類 庫 進 行 了 封 裝, 對 應 實 現 是nioserversocketchannel。

步驟 4:鏈路建立的時候建立並初始化 channelpipeline。channelpipeline

並不是 nio 服務端必需的,它本質就是乙個負責處理網路事件的職責鏈,負責管理和執行 channelhandler。

步驟 5:初始化 channelpipeline 完成之後,新增並設定 channelhandler。

channelhandler 是 netty 提 供 給 用 戶 定 制 和 擴 展 的 關 鍵 接 口。

步驟 6:繫結並啟動監聽埠。

步驟 7:selector 輪詢。

步 驟 8: 當 輪 詢 到 準 備 就 緒 的 channel 之 後, 就 由 reactor 線

程 nioeventloop 執 行 channelpipeline 的 相 應 方 法, 最 終 調 度 並 執 行channelhandler。

步 驟 9: 執 行 netty 系 統 channelhandler 和 用 戶 添 加 定 制 的

所有的 netty 伺服器都需要以下兩部分。

 至少乙個 channelhandler—該元件實現了伺服器對從客戶端接收的資料的處理,即它的業務邏輯。

 引導—這是配置伺服器的啟動**。至少,它會將伺服器繫結到它要監聽連線請求的埠上。

echo 客戶端和伺服器之間的互動是非常簡單的;在客戶端建立乙個連線之後,它會向伺服器傳送乙個或多個訊息,反過來,伺服器又會將每個訊息回送給客戶端。雖然它本身看起來好像用處不大,但它充分地體現了客戶端/伺服器系統中典型的請求-響應互動模式。

1.channelhandler 和業務邏輯

簡單設計乙個echoserverhandler,它需要實現 channelinboundhandler 介面,用 來定義響應入站事件的方法。這個簡單的應用程式只需要用到少量的這些方法,所以繼承 channelinboundhandleradapter 類也就足夠了,它提供了 channelinboundhandler 的預設實現。

除了 channelinboundhandleradapter 之外,還有很多需要學習的 channelhandler 的子型別和實現。

 針對不同型別的事件來呼叫 channelhandler;

 應用程式通過實現或者擴充套件 channelhandler 來掛鉤到事件的生命週期,並且提供自定義的應用程式邏輯;

 在架構上,channelhandler 有助於保持業務邏輯與網路處理**的分離。這簡化了開發過程,因為**必須不斷地演化以響應不斷變化的需求。

針對channelinboundhandleradapter 我們感興趣的方法是:

 channelread()—對於每個傳入的訊息都要呼叫;  channelreadcomplete()—通知channelinboundhandler最後一次對channelread()的呼叫是當前批量讀取中的最後一條訊息;  exceptioncaught()—在讀取操作期間,有異常丟擲時會呼叫。

**如下:

@sharable

//標示乙個channelhandler 可以被多個 channel 安全地共享

public

class

echoserverhandler

extends

channelinboundhandleradapter

@override

public

void

channelreadcomplete

(channelhandlercontext ctx)

throws exception

@override

public

void

exceptioncaught

(channelhandlercontext ctx, throwable cause)

throws exception

}

2.引導伺服器伺服器本身的過程了,具體涉及以下內容:

 繫結到伺服器將在其上監聽並接受傳入連線請求的埠;

 配置 channel,以將有關的入站訊息通知給 echoserverhandler 例項。

public

class

echoserver

public

void

start()

throws interruptedexception })

; channelfuture f = b.

bind()

.sync()

;//非同步地繫結伺服器;呼叫 sync()方法阻塞等待直到繫結完成

f.channel()

.closefuture()

.sync()

;//獲取 channel 的closefuture,並且阻塞當前執行緒直到完成

group.

shutdowngracefully()

.sync()

;//關閉eventloopgroup ,釋放所有的資源

}public

static

void

main

(string[

] args)

throws interruptedexception

}

總結:建立了乙個 serverbootstrap 例項。因為你正在使用的是 nio 傳輸,所以你指定了 nioeventloopgroup 來接受和處理新的連線,並且將 channel 的型別指定為 nioserversocketchannel 。在此之後,你將本地位址設定為乙個具有選定埠的 inetsocketaddress 。伺服器將繫結到這個位址以監聽新的連線請求。使用了乙個特殊的類——channelinitializer。這是關鍵。當乙個新的連線被接受時,乙個新的子 channel 將會被建立,而 channelinitializer 將會把乙個你的echoserverhandler 的例項新增到該 channel 的 channelpipeline 中。正如我們之前所解釋的,這個 channelhandler 將會收到有關入站訊息的通知。

接下來你繫結了伺服器 ,並等待繫結完成。(對 sync()方法的呼叫將導致當前 thread阻塞,一直到繫結操作完成為止)。在 處,該應用程式將會阻塞等待直到伺服器的 channel關閉(因為你在 channel 的 closefuture 上呼叫了 sync()方法)。然後,你將可以關閉eventloopgroup,並釋放所有的資源,包括所有被建立的執行緒 。

回顧一下剛完成的伺服器實現中的重要步驟。下面這些是伺服器的主要

**元件:

 echoserverhandler 實現了業務邏輯;

 main()方法引導了伺服器;

引導過程中所需要的步驟如下:

 建立乙個 serverbootstrap 的例項以引導和繫結伺服器;

 建立並分配乙個 nioeventloopgroup 例項以進行事件的處理,如接受新連線以及讀/寫資料;

 指定伺服器繫結的本地的 inetsocketaddress;

 使用乙個 echoserverhandler 的例項初始化每乙個新的 channel;

 呼叫 serverbootstrap.bind()方法以繫結伺服器。

至此,服務端簡單實現完成,在下一節中,將**對應的客戶端應用程式的**。

《網路程式設計》I O 模型

在分析 i o 模型之前,首先了解 同步 i o 和 非同步 i o 的基本概念 同步 i o 程序呼叫 i o 操作函式時,在 i o 操作函式返回之前,該程序會被掛起 即阻塞 直到 i o 操作完成後返回 非同步 i o 程序呼叫 i o 操作函式時,在 i o 操作函式返回之前,該程序不會被掛...

Linux網路程式設計(三) IO非阻塞操作

io非阻塞操作 sock的方法不一定非得是阻塞的,也可以非阻塞的操作。有兩種方法分別為設定fcntl 和設定相應函式的引數。服務端 include include include include include include include include define bufsize 128 i...

網路程式設計之IO模型 非同步IO

linux下的asynchronous io其實用得不多,從核心2.6版本才開始引入。先看一下它的流程 使用者程序發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到乙個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何bl...