王少輝++陳曉鵬
摘 要傳統的BIO技術在網絡通信中需要服務器為每一個鏈接都建立一個線程,如果其中已連接的請求沒有任何操作,將造成線程浪費。本文分析了BIO技術、NIO技術、AIO技術在網絡通信中的應用場合,解決了傳統BIO技術的不足,給出了其基本實現步驟及應用場景。
【關鍵詞】I/O NIO BIO SOCKET通信 Java 多線程
1 引言
傳統BIO技術在Socket通信中,系統需要為每一個鏈接建立一個線程去處理其請求,隨著客戶端的并發量不斷增加后,會導致線程數量的增加嚴重影響系統的性能。由于并發量的增加有可能導致服務器宕機,嚴重影響到用戶在使用過程中的良好體驗。為解決傳統BIO的不足,Java 中提供了新的API----NIO和NIO2來解決由于BIO技術帶來的系統瓶頸問題。在NIO中系統不再為每一個用戶請求注冊一個線程,而是通過通道將每一個鏈接都注冊到多路復用器上,通過多路復用器對注冊在其上的鏈接進行輪詢檢查,發現有鏈接請求才會開啟線程對其進行處理。NIO只在有連接請求時selector才會不斷輪詢檢查通道IO操作是否完成,與NIO技術不同的是AIO技術是異非步阻塞的。AIO中不再需要多路復用器,而是由異步非阻塞通道直接操作read和write方法。在客戶端讀寫請求發出后不再等待服務器的響應,而是處理完成后由操作系統來通知應用程序。AIO與NIO這兩種技術都極大地改變了傳統I/O流的不足。
2 Socket基本通信原理介紹
Socket是網絡通信中的其中一方,用來接收網絡通信中雙方其中一方的請求,方便的對雙方的數據進行傳輸。Socket通信分有連接的和無連接,面向連接的Socket通信與面向非連接的Socket通信相比有更高的可靠性和更有效的數據傳輸。本文基于有連接的套接字傳輸。
3 BIO、NIO、AIO技術比較
3.1 BIO技術簡介
BIO技術同步并且阻塞,在這種情況下,服務器需要為每一個連接開啟一個線程,只要有客戶端有請求服務器就需要開啟線程去進行處理。從客戶端傳來的每個請求,服務器都需要為其創建相應的線程去處理其請求。在BIO中,由于其線程的開銷很大,適合于運用在并發量小的場景下。其基本模型如圖1所示。
BIO網絡通信基本步驟:
3.1.1 服務低端
(1)創建ServerSocket并綁定監聽端口;
(2)創建Socket用來接收客戶端請求;
(3)創建輸入輸出流用來接收客戶端輸入或向客戶端輸出數據;
(4)關閉輸入輸出流等系統資源。
3.1.2 客戶端
(1)創建Socket綁定IP地址及端口;
(2)創建輸入輸出流用來接收服務器端相應或向服務器端發送數據;
(3)關閉輸入輸出流等系統資源。
3.2 NIO技術簡介
NIO技術即New IO技術,NIO技術由很多類和組件構成,其最重要的由channel、Buffer、和Selectors三個核心部分組成。
Channel:Java NIO中的通道類似于流,但又不完全相同。既可以從通道中讀取數據到Buffer也可以將數據從Buffer寫入通道中。其中SocketChannel和ServerSocketChannel是NIO中提供的用來解決Socket通信中的服務器性能問題的。SocketChannel通過TCP協議來讀取網絡中的數據,ServerSocketChannel用來接收鏈接來的請求以供服務器相應。
Buffer:Buffer是用來為數據提供緩沖區的。在NIO技術中,所有的數據都必須經過緩沖區。緩沖區本質上為一塊可讀可寫的內存塊,NIO中提供了不同數據類型的緩沖區來處理不同的數據請求,和一些基本的方法來操作緩沖區中的數據。
Selector:Selector是單線程來處理多個鏈接請求的關鍵。在Socket通信中,如果將多個鏈接請求注冊到多路復用器上,就可以用一個線程來處理多個鏈接請求,這樣就提高了Socket通信的效率。NIO通信中的網絡模型
如圖2所示。
NIO通信基本步驟:
3.2.1 服務器端
(1)創建多路復用器Selector 用來選擇通道;
(2)創建服務器端通道ServerSocketChannel;
(3)為多路復用器上注冊ServerSocketChannel用來將數據通過通道讀寫;
(4)申請Buffer存儲數據;
(5)多路選擇器通過其key值輪詢檢查通道讀寫Buffer中的數據完成其通信過程。
3.2.2 客戶端
(1)創建IP地址和端口號對應的SocketChannel ;
(2)將SocketChannel設置為非阻塞模式;
(3)創建多路復用器Selector注冊SocketChannel到多路選擇器;
(4)多路選擇器輪詢檢查通道從Buffer中讀寫數據。
在NIO網絡通信模型中,客戶端向服務器端發起鏈接請求,客戶端將數據寫入服務器端Buffer中,然后通過channel來從Buffer讀取數據或向Buffer寫入數據,對于通道中的數據必須經過選擇器來向服務器端的線程發起請求。而每一個多路選擇器對應一個線程模型,這樣一來,只有當鏈接請求有效時服務器才為客戶端開啟線程處理數據。對于同步阻塞的NIO模型中客戶端在向服務器端發送完數據后會不斷詢問I/O操作是否就緒才能進行下一步的操作。此模型中由于不需要為每一個鏈接請求創建一個線程,大大減少了線程之間的切換帶來的巨大開銷。提高了I/O的效率,使得在socket網絡通信更加高效。但由于NIO在鏈接請求中會不斷詢問I/O操作是否完成,其適合運用在短鏈接且并發量大的場合下。
3.3 AIO技術簡介
AIO即為異步非阻塞IO,與NIO不同的是,在這種模式下,客戶端發起一個鏈接請求后不在詢問服務器端的I/O操作是否完成便立即返回。在使用過程中只需直接調用異步的read和write方法來讀寫數據,在讀寫過程完畢后由操作系統主動通知應用程序讀寫操作是否完成。由AIO的讀寫過程可以看出,因為在讀寫完成后客戶端不需要再詢問服務器端是完成了I/O操作,所以AIO非常適合于運用在那些并發量大且長連接的請求。AIO模型如圖3所示。
AIO中有幾個比較重要的類:
AsynchronousServerSocket:用來創建服務器端的ServerSocket并綁定地址監聽端口。
AsynchronousSocketChannel:Socket在異步非阻塞通信中的應用,用來表示一個連接請求,并用來在通信過程中傳遞數據。
AsynchronousChannelGroup:異步通道的分組管理,目的是問了資源共享。創建AsynchronousChannelGroup時需要為其綁定一個線程執行器對象,這個線程池主要完成兩個任務:處理I/O事件和派發CompletionHandler。在創建AsynchronousServerSocket時需要為其綁定一個AsynchronousChannelGroup。通過AsynchronousServerSocket創建的AsynchronousChannelGroup將屬于同一組,共享其中資源。
CompletionHandler:用于定義在異步IO操作完成后的回調接口。
3.3.1 服務器端
(1)創建AsynchronousChannelGroup;
(2)創建AsynchronousServerSocketChannel并將它綁定在AsynchronousChannelGroup上;
(3)為AsynchronousServerSocketChannel對象綁定端口號;
(4)調用accept()接收客戶端請求實現CompletionHandler接口調用讀寫方法進行讀寫數據。
3.3.2 客戶端
(1)創建AsynchronousSocketChannel;
(2)綁定IP地址和端口號鏈接服務低端實現CompletionHandler接口中方法直接進行讀寫數據。
3.4 各種I/O技術比較分析
BIO:同步阻塞I/O,使用難度簡單,可靠性低,適用于鏈接并發量小的架構且對服務器資源依賴更高。
NIO:同步非阻塞I/O,使用難度復雜,可靠性高,適用于并發量大且鏈接較短的場景。
AIO:異步非阻塞I/O,使用難度一般,可靠性高,適用于并發量大且鏈接長的場景。
4 結語
傳統網絡在IO處理方面存在著性能不足的問題,NIO與AIO包的引入解決了傳統IO性能瓶頸問題,使的Java在網絡通信中有了更搞得效率。對于不同的IO來說,它們各自有有不同的應用領域。對于那些并發量小,數據傳輸量小的場景來說,傳統的BIO完全可以勝任其工作。相反對于那些對性能要求比較高,并發量大且對IO的要求比較搞得場合來說應該選擇NIO或者BIO技術。如果客戶端與服務器在長連接的情況下選擇AIO相比NIO會更加高效一些。相反,如果是短連接的應用領域,則推薦使用NIO。
參考文獻
[1]范寶德,馬建生.Java非阻塞通訊研究[J].微計算機信息,2006,22(12-3):116-119.
[2]劉邦桂,李正凡.用Java實現流式Socket通訊[J].華東交通大學學報,2007,24(05):110-112.
[3]封瑋,周世平.基于Java NIO的非阻塞通信的研究與實現[J].計算機系統應用,2004(09):32-35.
[5]任小強,陳金鷹,李文彬,胡波.網絡通信之Java Socket多線程通信[J].信息通信,2015(06):206-207.
作者簡介
王少輝(1992-),男,山西省平順縣人。碩士學位。現為山東大學(威海)機電與信息工程學院學生。主要研究方向為電路與系統。
陳曉鵬(1992-),男,天津市人。碩士學位。現為山東大學(威海)機電與信息工程學院學生。主要研究方向為電路與系統。
作者單位
山東大學(威海)機電與信息工程學院 山東省威海市 264209