国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

NIO-Selector 網絡編程

這篇具有很好參考價值的文章主要介紹了NIO-Selector 網絡編程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一、阻塞 & 非阻塞

1、阻塞

2、非阻塞

二、selector

1、連接和讀取

2、處理客戶端斷開

3、處理消息的邊界

4、ByteBuffer大小分配

三、多線程優(yōu)化

四、NIO vs BIO

1、stream vs channnel

2、IO模型

阻塞IO

非阻塞IO

多路復用

異步IO模型


一、阻塞 & 非阻塞

1、阻塞

服務器端的代碼

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

然后創(chuàng)建客戶端,直接連服務器端的代碼就可以了

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

運行發(fā)現服務端線程執(zhí)行到accept這個方法后就停止運行了,這個方法是阻塞的,要等連接建立完成之后才能繼續(xù)運行;建立完連接后走到read方法又會阻塞等待讀入數據,讀到數據之后才能恢復運行。

當有多個客戶端的時候,服務端在執(zhí)行到一個客戶端的堵塞方法的時候會一直等待,其他客戶端就不會被處理。?

2、非阻塞

我們可以把ServerSocoketChannel和SocketChannel改成非阻塞模式,這樣如果沒有連接直接返回null,沒有讀取到數據就返回0,不會去堵塞等待了。

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

但是這樣也會有缺點,因為線程是一直循環(huán)檢查有沒有鏈接和數據的,如果一直沒有連接和數據來,線程依然會不斷循環(huán),太過繁忙了,所以這種非阻塞模式在開發(fā)中也不常用。

二、selector

為了解決上面非堵塞的不斷循環(huán)問題,我們就引入selector,接下里看看selector的使用

1、連接和讀取

用的時候我們要先調用靜態(tài)open方法創(chuàng)建Selector對象,然后來管理這些channel,channel調用register方法注冊到selector,返回值是個SelectionKey對象,?SelectionKey就是將來事件發(fā)生后,通過它可以知道事件是哪個channel的事件,然后調用interstOps設置對哪個事件感興趣

channel事件有4中類型:

  • accept-有連接請求的時候觸發(fā)
  • connect-客戶端連接建立后觸發(fā)
  • read-數據可讀時
  • write-可寫事件

然后監(jiān)聽的時候用select()方法,沒有時間發(fā)生的時候線程堵塞,有事件才執(zhí)行,然后遍歷集合調用selectedKey方法處理事件。

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

如果我們遍歷出來不對事件處理,那么下次遍歷的時候還會有,也就是說如果有未處理事件,那么是不會阻塞的,如果不想處理的話,我們可以用cannel()方法來取消處理

socket處理的時候要想不去不斷循環(huán)讀取,那么也要交給selector管理,所以這個socketChannel也要調用register方法注冊到selector上,還有感興趣關注的事件

這里要把監(jiān)聽到的事件類型分開處理

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

這個代碼在運行的時候缺空指針了,為什么呢?

selector的集合和selectedKeys集合中每次監(jiān)聽事件中的內容執(zhí)行完是不會自己刪除的,所以我們第一次執(zhí)行完第二次遍歷到有元素執(zhí)行,建立連接的時候卻沒有需要建立的返回null,這個時候就拋出空指針了,我們每次執(zhí)行完一個事件就得手動從容器刪除

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

2、處理客戶端斷開

我們客戶端和服務器連接之后,如果客戶端退出會拋出異常,如果我們直接try catch去抓的話會循環(huán),因為客戶端關閉會引發(fā)read事假,這個事假一直不處理就會一直執(zhí)行,所以我們必須在catch里面去把key調用cancel()方法取消處理事件

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

但是如果是正常斷開呢,還是會循環(huán),因為正常斷開執(zhí)行不到catch語句不會cancel,就會一直循環(huán)處理close這個read事件,所以我們要用read的返回值來區(qū)分是不是close指令,是就取消處理掉

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

3、處理消息的邊界

看看下面這種邊界問題:

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

我們用分割符的方法來解決邊界的問題,遇到分隔符就說明讀取結束了,我們就分割成一個消息

如果我們實際的內容超過了byteBuffer,一次沒有讀取完不會報錯,第二個會把剩下的部分發(fā)過來會當成一個完整的消息處理,所以當空間不夠的時候,我們需要擴容,而且我們不能把byteBuffer做為局部變量,要當共享的第一個和第二次共用一個byteBuffer。擴容我們是重新搞個更大的buffer2,然后第一次復制過去,第二次的直接讀過去

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

1、我們先修正ByteBuffer不能為局部變量,但是我們不能直接放最外層,因為如果放最外層就變成多個socketChannel公用一個ByteBuffer,這樣就亂了,應該每個channel都有自己的byteBuffer,這里就要用到attachment附件,我們可以在注冊的時候把buffer當成附件(Object)一起注冊為SelectionKey里面。后面要用的時候直接用key調用attachment方法就能獲取到buffer

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

?2、擴容的時候就是比較如果壓縮后的長度和限制最大的長度相等,說明這個消息超過了要擴容,壓縮就是每次讀取完一個分割符后都要進行的,這個壓縮方法就是把因為讀取的去除

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

4、ByteBuffer大小分配

每個channel都需要記錄可能被分割的消息,因為byteBuffer不能被多個channel共同使用,因此需要每個channel維護一個獨立的byteBuffer

ByteBuffer不能太大,太大的話很多連接就需要很大內存了,因此需要設計大小可變的byteBuffer。一種思路是首先分配一個小buffer,比如4k,如果不夠再擴容為8k,用新的替換掉舊的,優(yōu)點是消息連續(xù)容易處理,缺點是數據拷貝耗性能。另一個思路是多個數組組成buffer,一個數組不夠,把多出來的內容寫入新的數組,與前面的區(qū)別是消息存儲不連續(xù)解析復雜,優(yōu)點是避免了拷貝引起的性能損耗。

三、多線程優(yōu)化

現在的處理都是單線程的,沒有充分利用多核cpu,

我們可以向下圖這樣優(yōu)化,分為boss好worker,boss負責建立連接,而worker負責讀寫操作,如果連接了,可以直接去worker讀,worker里面有一個selector,線程數可以很多很多,不可能一直建立很多worker,所以一個worker可以管理多個channel,多個thread,相當于把任務分擔了。

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

問題:?

執(zhí)行我們現在是worker-0不斷循環(huán)執(zhí)行select方法和boss的register可能會有問題,因為他們是同一個selector管理,又是不同線程的,如果上面執(zhí)行的selector執(zhí)行select方法會阻塞,所以下面register就不能執(zhí)行。

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

我們可以把上面的worker.registery方法移動到sc.register上一行,這樣就有可能會先執(zhí)行到register,再執(zhí)行worker.registery()里面的select方法,register不會阻塞直接執(zhí)行完這樣就不會有問題了,因為他們是兩個線程,所以可能是先執(zhí)行的register,執(zhí)行完又會停留到select方法上阻塞,這個時候如果來了個新的客戶端,所以肯定阻塞又出現了那個問題

解決:

我們要想一個辦法,參考netty的解決辦法,讓他們在同一個線程內執(zhí)行,這樣就可以管理執(zhí)行順序了。

我們在搞個隊列,然后注冊的方法里像隊列中添加一個注冊的任務

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO?NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

這樣我們就能保證是worker-0在執(zhí)行任務的時候,就會去注冊了,就能保證在worker-0來執(zhí)行這兩個事件了,實現兩個線程的事件用一個線程執(zhí)行,這樣就可以控制順序。最后要注意,添加完事件之后要喚醒selector因為那邊的selector是一直阻塞狀態(tài)的

回顧下整體流程:

我們先接收連接,調用worker進行register去初始化,如果是第一次就會把selector線程都創(chuàng)建好,如果是第二次,都會向隊列加入任務,這個worker-0的run進來是select就是阻塞住如果沒有的話,然后隊列加入完任務就會喚醒這個阻塞的worker執(zhí)行任務,繼續(xù)他執(zhí)行完又select沒任務阻塞了。

四、NIO vs BIO

1、stream vs channnel

  • stream不會自動緩沖數據,channel會利用系統(tǒng)提供的發(fā)送緩沖區(qū),接收緩沖區(qū)(更底層)
  • stream僅支持阻塞API,channel同時支持阻塞、非阻塞API,網絡channel可配合selector實現多路復用
  • 二者均為全雙工,即讀寫可以同時進行

2、IO模型

當調用channel的read方法或stream的read后,會由用戶態(tài)切換至操作系統(tǒng)內核態(tài)來完成真正的數據讀取,而讀取又分為兩個階段:等待數據階段復制階段

阻塞IO

當調用read切換內核態(tài)后,如果沒有數據過來,就會等待數據,等數據到了之后處理好了,復制數據完成之后才切換回用戶態(tài),這個整個過程用戶線程是阻塞的

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

非阻塞IO

用戶線程會一直循環(huán)切換內核態(tài)看看有沒有數據,沒有就立即返回,然后繼續(xù)轉化,用戶線程始終在運行,這就算非阻塞IO,但是正在有數據復制數據的時候還是阻塞的(這種切換太頻繁了,可能會影響系統(tǒng)性能)

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

多路復用

多路復用一上來不是調用read,而是用select等待事件(這個是阻塞的),如果有內核態(tài)會告訴他,這個時候再切換過去復制數據(復制的時候還是需要阻塞)?

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

他們都是阻塞,那比阻塞的優(yōu)勢在哪里呢?看看下面的圖就知道了,阻塞IO的時候,如果當read在阻塞等待的時候,其他還有線程要執(zhí)行別的操作,他必須等待這個read阻塞完成全部完成才執(zhí)行;而多路復用selector可以檢測多個事件,什么事件都可以觸發(fā)喚醒他運行,也就是他阻塞的時候等的是一批事件不是一個事件。

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO

異步IO模型

  • 同步:線程自己去獲取結果(一個線程)
  • 異步:線程自己不去獲取結果,而是由其他線程送結果(至少兩個線程)

我們先分析一下上面三種是同步還是異步

  • 阻塞IO就是同步的,是用戶線程自己發(fā)起read,也是自己阻塞等待接受accept的,所以是同步的,所以也叫同步阻塞IO
  • 非阻塞IO也是同步的,他也是線程自己發(fā)送自己接受,只不過他是不斷循環(huán)去發(fā)送,同步非阻塞
  • 多路復用也是同步的,他也是自己發(fā)送select之類的等待阻塞,有事件了喚醒自己去執(zhí)行,還是自己發(fā)自己阻塞自己做,也是同步的

異步阻塞是怎么樣的呢?

他是這樣的,客戶端線程read后,直接返回一個回調函數和參數,然后會異步啟動線程2去等待數據和復制數據,復制完后用回調方法通知結果。?所以也這種就是非阻塞的,請求完直接返回了,所以也叫異步非阻塞

NIO-Selector 網絡編程,netty,網絡,java,netty,NIO文章來源地址http://www.zghlxwxcb.cn/news/detail-521342.html

到了這里,關于NIO-Selector 網絡編程的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【Netty專題】【網絡編程】從OSI、TCP/IP網絡模型開始到BIO、NIO(Netty前置知識)

    【Netty專題】【網絡編程】從OSI、TCP/IP網絡模型開始到BIO、NIO(Netty前置知識)

    我是有點怕網絡編程的,總有點【談網色變】的感覺。為了讓自己不再【談網色變】,所以我想過系統(tǒng)學習一下,然后再做個筆記這樣,加深一下理解。但是真要系統(tǒng)學習,其實還是要花費不少時間的,所以這里也只是簡單的,盡可能地覆蓋一下,梳理一些我認為比較迫切需

    2024年02月06日
    瀏覽(28)
  • java網絡編程——NIO架構

    java網絡編程——NIO架構

    目錄 1.什么是NIO 2.NIO結構 3.基于NIO下的聊天系統(tǒng)實現 4.Netty NIO:java non-blocking IO,同步非阻塞IO。 BIO是阻塞IO,即每一個事件都需要分配一個進程給他,如果客戶端沒有連接上,則一直阻塞等待。 而NIO,異步 I/O 是一種沒有阻塞地讀寫數據的方法:該架構下我們可以注冊對特定

    2023年04月26日
    瀏覽(23)
  • 快速入門java網絡編程基礎------Nio

    快速入門java網絡編程基礎------Nio

    嗶哩嗶哩黑馬程序員 netty實戰(zhàn)視頻 NIO(New I/O)是Java中提供的一種基于通道和緩沖區(qū)的I/O(Input/Output)模型。它是相對于傳統(tǒng)的IO(InputStream和OutputStream)模型而言的新型I/O模型。NIO的主要特點包括: 1.通道與緩沖區(qū): 2.NIO引入了通道(Channel)和緩沖區(qū)(Buffer)的概念。通道

    2024年01月20日
    瀏覽(29)
  • Java網絡編程-深入理解BIO、NIO

    Java網絡編程-深入理解BIO、NIO

    BIO BIO 為 Blocked-IO(阻塞 IO),在 JDK1.4 之前建立網絡連接時,只能使用 BIO 使用 BIO 時,服務端會對客戶端的每個請求都建立一個線程進行處理,客戶端向服務端發(fā)送請求后,先咨詢服務端是否有線程響應,如果沒有就會等待或者被拒絕 BIO 基本使用代碼: 服務端: 客戶端:

    2024年02月04日
    瀏覽(24)
  • BIO、NIO、IO多路復用模型詳細介紹&Java NIO 網絡編程

    BIO、NIO、IO多路復用模型詳細介紹&Java NIO 網絡編程

    上文介紹了網絡編程的基礎知識,并基于 Java 編寫了 BIO 的網絡編程。我們知道 BIO 模型是存在巨大問題的,比如 C10K 問題,其本質就是因其阻塞原因,導致如果想要承受更多的請求就必須有足夠多的線程,但是足夠多的線程會帶來內存占用問題、CPU上下文切換帶來的性能問題

    2024年02月14日
    瀏覽(30)
  • Java網絡編程----通過實現簡易聊天工具來聊聊NIO

    Java網絡編程----通過實現簡易聊天工具來聊聊NIO

    前文我們說過了BIO,今天我們聊聊NIO。 NIO 是什么?NIO官方解釋它為 New lO ,由于其特性我們也稱之為,Non-Blocking IO。這是jdk1.4之后新增的一套IO標準。 為什么要用NIO呢? 我們再簡單回顧下BIO: 阻塞式IO,原理很簡單,其實就是多個端點與服務端進行通信時,每個客戶端有一個

    2024年02月05日
    瀏覽(20)
  • Netty實戰(zhàn)專欄 | Java網絡編程深入解析

    Netty實戰(zhàn)專欄 | Java網絡編程深入解析

    ?作者簡介:大家好,我是Leo,熱愛Java后端開發(fā)者,一個想要與大家共同進步的男人???? ??個人主頁:Leo的博客 ??當前專欄: Netty實戰(zhàn)專欄 ?特色專欄: MySQL學習 ??本文內容:Netty實戰(zhàn)專欄 | Java網絡編程深入解析 ???個人小站 :個人博客,歡迎大家訪問 ??個人知識

    2024年02月06日
    瀏覽(23)
  • NIO基礎 - 網絡編程

    NIO基礎 - 網絡編程

    non-blocking io 非阻塞 IO 1.1 Channel Buffer channel 有一點類似于 stream,它就是讀寫數據的 雙向通道 ,可以從 channel 將數據讀入 buffer,也可以將 buffer 的數據寫入 channel,而之前的 stream 要么是輸入,要么是輸出,channel 比 stream 更為底層 常見的 Channel 有 FileChannel DatagramChannel SocketCh

    2024年02月02日
    瀏覽(20)
  • 10.NIO 網絡編程應用實例-群聊系統(tǒng)

    需求:進一步理解 NIO 非阻塞網絡編程機制,實現多人群聊 編寫一個 NIO 群聊系統(tǒng),實現客戶端與客戶端的通信需求(非阻塞) 服務器端:可以監(jiān)測用戶上線,離線,并實現消息轉發(fā)功能 客戶端:通過 channel 可以無阻塞發(fā)送消息給其它所有客戶端用戶,同時可以接受其它客戶端用

    2024年02月15日
    瀏覽(44)
  • 使用Netty實現Socket網絡編程

    ** ** Netty支持多種網絡通信模型,包括傳統(tǒng)的阻塞I/O、非阻塞I/O、多路復用I/O和異步I/O。其中,非阻塞I/O和多路復用I/O是Netty的核心特性。 非阻塞I/O :Netty通過使用Java的NIO(New I/O)庫,實現了非阻塞的I/O操作。這意味著當一個操作正在進行時,不會阻塞線程,線程可以繼續(xù)處

    2024年01月16日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包