NIO:异步非阻塞I/O,AIO,BIO
Neety的基礎(chǔ)使用及說明
https://www.cnblogs.com/rrong/p/9712847.html
BIO(缺乏彈性伸縮能力,并發(fā)量小,容易出現(xiàn)內(nèi)存溢出,出現(xiàn)宕機 每一個客戶端對應一個線程
偽異步IO:創(chuàng)建線程池,由線程池里邊的線程負責連接處理,M個個請求進來時,會在線程池創(chuàng)建N個線程。容易出現(xiàn)線程池阻塞。由一個線程池來處理客戶端的請求。
NIO:異步非阻塞,服務器實現(xiàn)模式為一個請求一個線程,客戶端發(fā)送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
對于NIO,有兩點需要強調(diào)的:
(1)關(guān)于概念有兩種理解,New I/O(相對于之前的I/O庫是新增的)和Non-block I/O(非阻塞的)。由于NIO的目標就是讓java支持非阻塞I/O,所有更多人喜歡用Non-block I/O。
(2)很多人喜歡將NIO稱為異步非阻塞I/O,但是,如果按照嚴格的NUIX網(wǎng)絡編程模型和JDK的實現(xiàn)進行區(qū)分,實際上它只是非阻塞I/O,不能稱之為異步非阻塞I/O。但由于NIO庫支持非阻塞讀和寫,相對于之前的同步阻塞讀和寫,它是異步的,因此很多人習慣稱NIO為異步非阻塞I/O。
AIO: JDK1.7升級了NIO庫,升級后的NIO庫被稱為NIO2.0,正式引入了異步通道的概念。NIO2.0的異步套接字通道是真正的異步非阻塞I/O,此即AIO。其服務器實現(xiàn)模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理。
BIO(一請求以應答模型): 一個獨立的acceptor監(jiān)聽客戶端的連接,監(jiān)聽到客戶端的請求連接之后,為每個客戶端創(chuàng)建一個新的線程,進行鏈路處理。處理完之后,通過輸出流返回給應答客戶端,此時線程銷毀。
以上解釋也可參考博文https://blog.csdn.net/u012285489/article/details/44646813
Netty服務器的原理:
圖中每次請求的讀取是通過UpStream來實現(xiàn),然后激活我們的服務邏輯如EchoServerHandler,而服務器向外寫數(shù)據(jù),也就是響應是通過DownStream實現(xiàn)的。每個通道Channel包含一對UpStream和DownStream,以及我們的handlers(EchoServerHandler),如下圖,這些都是通過channel pipeline封裝起來的,數(shù)據(jù)流在管道里流動,每個Socket對應一個ChannelPipeline。
channel pipeline是關(guān)鍵:
為每個Channel 保留 ChannelHandlers ,如EchoServerHandler
所有的事件都要通過它
一個Channel對應一個 ChannelPipeline
包含協(xié)議編碼解碼 安全驗證SSL/TLS和應用邏輯
非阻塞的IO通信框架
Netty概述:
1、netty是基于Java NIO的網(wǎng)絡應用框架,client-server框架
2、Netty是一個高性能、異步事件驅(qū)動的NIO框架,它提供了對TCP、UDP和文件傳輸?shù)闹С郑?br />
作為一個異步NIO框架,Netty的所有IO操作都是異步非阻塞的,
通過Future-Listener機制,用戶可以方便的主動獲取或者通過通知機制獲得IO操作結(jié)果。
3、作為當前最流行的NIO框架,Netty在互聯(lián)網(wǎng)領(lǐng)域、大數(shù)據(jù)分布式計算領(lǐng)域、游戲行業(yè)、通信行業(yè)等獲得了廣泛的應用,
Netty的使用:
1.創(chuàng)建一個服務器端(ServerBootstrap)
1.需要創(chuàng)建兩個對象, new NioEventLoopGroup();
2.然后創(chuàng)建一個服務器端的對象new ServerBootstrap();
3.使用服務器對象調(diào)用group方法將第一步創(chuàng)建的兩個對象傳入到服務器對象中。
4.然后再調(diào)用channel方法傳入NioServerSocketChannel.class
5.在接著調(diào)用childHandler方法,傳入繼承了ChannelInitializer的類。注:此類用于對剛剛接收的channel進行初始化。(可進行設(shè)置接收傳輸數(shù)據(jù)的編碼和解碼與添加自定義處理邏輯的類,需要繼承SimpleChannelInboundHandler。然后重寫該類的方法進行自己邏輯部分的處理)
6.在實現(xiàn)了ChannelInitializer類中實現(xiàn) 了initChaannel方法,然后需要獲取ChannelPipeline這個類來進行設(shè)置,獲取方法是:通過該實現(xiàn)方法的參數(shù).pipeline方法來得到。從而可以進行設(shè)置接收到channel進行編碼解碼的設(shè)置與添加自己邏輯部分的類。
7.添加自己的邏輯部分的類或代碼了。使用上步得到的CHannelPipeline來調(diào)用addLast方法添加。設(shè)置編碼和解碼也一樣。,附圖:
8.開始編寫繼承了SimpleChannelInboundHandler類的類,然后重寫該類的一些方法來完成自己的邏輯代碼。
channelActive():建立連接的時候觸發(fā)
channelRead0():收到客戶端發(fā)來的消息的時候觸發(fā)
.....
9.綁定端口開始接收進來的連接,使用服務器端對象調(diào)用bind方法綁定端口號然后調(diào)用sync方法來進行監(jiān)聽并接受連接
10.關(guān)閉服務器使用 future.channel().closeFuture().sync();來關(guān)閉服務器
并關(guān)閉第一步所創(chuàng)建的兩個NioEventLoopGroup。調(diào)用shutdownGracefully方法
注:上述為創(chuàng)建了一個服務器端步驟
如果在繼承了SimpleChannelInboundHandler類的上邊添加@Sharable注解
第五步必須為調(diào)用childHandler,否則報錯childHandler not set
注解解釋:
@Sharable // 表示它可以被添加到多個ChannelPipeline中。
2.創(chuàng)建一個客戶端(Bootstrap)
1.創(chuàng)建一個NioEventLoopGroup對象,用來傳入下班創(chuàng)建的Bootstrap客戶端對象。
2.創(chuàng)建Bootstrap客戶端對象
3.使用創(chuàng)建的客戶端對象調(diào)用group對象竄入創(chuàng)建 NioEventLoopGroup對象。然后下邊和創(chuàng)建服務器端對象的步驟一樣到第9步。注:這里跟服務器端第五步稍微有點區(qū)別,客戶端調(diào)用的是handler方法,而服務器端調(diào)用的是childHandler方法
4.開始連接服務器,使用創(chuàng)建的客戶端對象調(diào)用connect對象將所需要連接的服務器ip及端口號。然后再調(diào)用sync方法進行與服務器的連接。
5.向服務器端發(fā)送數(shù)據(jù),需要創(chuàng)建一個Channel對象,使用第四步創(chuàng)建的對象嗲用channel方法得到一個Channel對象。然后使用該對象調(diào)用writeAndFlush方法來像服務器端發(fā)送數(shù)據(jù)。
6.關(guān)閉當前與服務器連接的話將第一步創(chuàng)建的NioEventLoopGroup對象關(guān)閉即可,調(diào)用shutdownGracefully方法。
注:可參考博文:https://blog.csdn.net/javadhh/article/details/66477423
以上為本人自己理解。如有不對,還請指出!
總結(jié)
以上是生活随笔為你收集整理的NIO:异步非阻塞I/O,AIO,BIO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Irrlicht 3D Engine 笔
- 下一篇: docker启动容器报错 Unknown