日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Netty - I/O模型之NIO

發(fā)布時(shí)間:2025/3/21 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty - I/O模型之NIO 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • Non Blocking I/O 同步非阻塞模型
  • Code
    • Server
    • Client
    • 日志及需要優(yōu)化的地方
    • 優(yōu)化 (多路復(fù)用器)
  • 小結(jié)


Non Blocking I/O 同步非阻塞模型

同步非阻塞

一個(gè)線程可以處理多個(gè)請(qǐng)求(連接),客戶端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器selector上,多路復(fù)用器輪詢到連接有IO請(qǐng)求就進(jìn)行處理。

JDK1.4開始引入


Code

Server

package com.artisan.iomodel.nio;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Iterator; import java.util.List;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:06* @mark: show me the code , change the world*/public class NioServer {// 保存客戶端連接static List<SocketChannel> channelList = new ArrayList<>();public static void main(String[] args) throws IOException {// 創(chuàng)建NIO ServerSocketChannel,與BIO的serverSocket類似ServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 設(shè)置ServerSocketChannel為非阻塞serverSocket.configureBlocking(false);System.out.println("服務(wù)啟動(dòng)成功");while (true) {// 非阻塞模式accept方法不會(huì)阻塞,否則會(huì)阻塞// NIO的非阻塞是由操作系統(tǒng)內(nèi)部實(shí)現(xiàn)的,底層調(diào)用了linux內(nèi)核的accept函數(shù)SocketChannel socketChannel = serverSocket.accept();if (socketChannel != null) { // 如果有客戶端進(jìn)行連接System.out.println("連接成功");// 設(shè)置SocketChannel為非阻塞socketChannel.configureBlocking(false);// 保存客戶端連接在List中channelList.add(socketChannel);}// 遍歷連接進(jìn)行數(shù)據(jù)讀取Iterator<SocketChannel> iterator = channelList.iterator();while (iterator.hasNext()) {SocketChannel sc = iterator.next();ByteBuffer byteBuffer = ByteBuffer.allocate(128);// 非阻塞模式read方法不會(huì)阻塞,否則會(huì)阻塞int len = sc.read(byteBuffer);// 如果有數(shù)據(jù),把數(shù)據(jù)打印出來(lái)if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客戶端斷開,把socket從集合中去掉iterator.remove();System.out.println("客戶端斷開連接");}}}} }

Client

我們用cmd工具來(lái)連一下 , telnet 127.0.0.1 7777

回車,輸入 ctrl + ]

發(fā)送消息


日志及需要優(yōu)化的地方

舉個(gè)例子,如果連接數(shù)太多的話,會(huì)有大量的無(wú)效遍歷,假如有1萬(wàn)個(gè)連接,其中只有1000個(gè)連接有寫數(shù)據(jù),但是由于其他9000個(gè)連接并沒(méi)有斷開,我們還是要每次輪詢遍歷一萬(wàn)次,其中有十分之九的遍歷都是無(wú)效的…是不是有點(diǎn)不妥當(dāng)呢?


優(yōu)化 (多路復(fù)用器)

為了優(yōu)化這個(gè)問(wèn)題 , NIO引入多路復(fù)用器

package com.artisan.iomodel.nio;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; /*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:50* @mark: show me the code , change the world*/ public class NioSelectorServer {public static void main(String[] args) throws IOException, InterruptedException {// 創(chuàng)建NIO ServerSocketChannelServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 設(shè)置ServerSocketChannel為非阻塞serverSocket.configureBlocking(false);// 打開Selector處理Channel,即創(chuàng)建epollSelector selector = Selector.open();// 把ServerSocketChannel注冊(cè)到selector上,并且selector對(duì)客戶端accept連接操作感興趣serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服務(wù)啟動(dòng)成功");while (true) {// 阻塞等待需要處理的事件發(fā)生selector.select();// 獲取selector中注冊(cè)的全部事件的 SelectionKey 實(shí)例Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍歷SelectionKey對(duì)事件進(jìn)行處理while (iterator.hasNext()) {SelectionKey key = iterator.next();// 如果是OP_ACCEPT事件,則進(jìn)行連接獲取和事件注冊(cè)if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);// 這里只注冊(cè)了讀事件,如果需要給客戶端發(fā)送數(shù)據(jù)可以注冊(cè)寫事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客戶端連接成功");} else if (key.isReadable()) { // 如果是OP_READ事件,則進(jìn)行讀取和打印SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = socketChannel.read(byteBuffer);// 如果有數(shù)據(jù),把數(shù)據(jù)打印出來(lái)if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客戶端斷開連接,關(guān)閉SocketSystem.out.println("客戶端斷開連接");socketChannel.close();}}//從事件集合里刪除本次處理的key,防止下次select重復(fù)處理iterator.remove();}}} }


小結(jié)

NIO方式適用于連接數(shù)目多且連接比較短(輕操作) 的架構(gòu), 比如聊天服務(wù)器, 彈幕系統(tǒng), 服務(wù)器間通訊,但編程比較復(fù)雜

總結(jié)

以上是生活随笔為你收集整理的Netty - I/O模型之NIO的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。