NIO核心三:Selector

这篇具有很好参考价值的文章主要介绍了NIO核心三:Selector。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、基本概念

选择器提供一种选择执行已经就绪的任务的能力。selector选择器可以让单线程处理多个通道。如果程序打开了多个连接通道,每个连接的流量都比较低,可以使用Selector对通道进行管理。
NIO核心三:Selector,java AIO BIO NIO,nio,java

二、如何创建选择器

1.创建Selector

Selector selector = Selector.open();

2.必须将通道设置为非阻塞模式才能注册到选择器上

Channel.configureBlocking(false);

3.把通道注册到选择器上,会返回一个选择键

SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);

SelectionKey的操作有:

  • SelectionKey.OP_CONNECT,指某个通道连接到服务器
  • SelectionKey.OP_ACCEPT,只有ServerSocketChannel有这个事件,查看是否有新的连接
  • SelectionKey.OP_READ,是否有可读的通道就绪
  • SelectionKey.OP_WRITE,写数据的通道是否就绪

注册完成后,可以调用select()方法轮询是否有就绪的通道

int count = selector.select();

select()方法,返回就绪的通道数量

三、服务器端模板

//服务器端模板代码
public static void Server_Standard_Code_template() {
    try {
        ServerSocketChannel ssc=ServerSocketChannel.open();
        ssc.socket().bind(new InetSocketAddress("localhost",80));
        //只有设置为非阻塞才能注册到选择器中
        ssc.configureBlocking(false);
        //创建一个选择器
        Selector selector = Selector.open();
        //通道注册进选择器中---监听客户端连接事件
        ssc.register(selector, SelectionKey.OP_ACCEPT);

        while(true){
            //获取以及就绪的通道数量
            int select = selector.select();
            //没有通道就绪
            if(select==0)
            {
                continue;
            }
            //获取已经就绪的
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext())
            {
                SelectionKey selectionKey = iterator.next();
                //客户端连接请求事件
                if(selectionKey.isAcceptable())
                {
                    //接收连接
                }else if(selectionKey.isReadable())
                {
                    //读取数据
                }
                else if(selectionKey.isWritable())
                {
                    //写数据
                }
                //移除
                iterator.remove();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

四、NIO通讯实例

服务器端

public class NIOServer {
    //通道管理器
    private Selector selector;

    /**
     * 获取一个ServerSocket通道,并对该通道做一些初始化工作
     * @param port 端口号
     * @throws IOException
     */
    public void initServer(int port) throws IOException {
        //获取一个ServerSocket通道
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        //设置通道为非阻塞
        socketChannel.configureBlocking(false);
        //将通道对应的ServerSocket绑定到port端口
        socketChannel.socket().bind(new InetSocketAddress(port));
        //获取一个通道管理器
        this.selector = Selector.open();
        /**
         * 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件
         * 注册该事件后,当该事件到达时,selector.select()会返回
         * 如果该事件没有到达,selector.select()会一直阻塞
         */
        socketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    public void listen() throws IOException {
        while (true){
            //当注册的事件到达时,方法返回,否则该方法一直阻塞
            selector.select();
            //获取selector中选项的迭代器
            Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                //删除已经选择的key,防止重复处理
                iterator.remove();
                //客户端连接请求事件
                if(key.isAcceptable()){
                    //接收连接
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                    //获取客户端连接的通道
                    SocketChannel channel = serverSocketChannel.accept();
                    //设置为非阻塞
                    channel.configureBlocking(false);
                    //向客户端发送数据源
                    ByteBuffer buf = ByteBuffer.allocate(1024);
                    String message = "你好我是服务器端,我接收到了你的消息";
                    buf.put(message.getBytes(StandardCharsets.UTF_8));
                    //把缓冲区切换成读取模式
                    buf.flip();
                    //将buffer写入channel
                    while (buf.hasRemaining()){
                        channel.write(buf);
                    }
                    //和客户端连接成功后,为了接收到客户端的信息,需要给通道设置读取权限
                    channel.register(this.selector,SelectionKey.OP_READ);
                }else if(key.isReadable()){
                    //读取数据
                    read(key);
                }
            }
        }
    }

    public void read(SelectionKey key) throws IOException {
        //得到事件发生的socket通道
        SocketChannel channel = (SocketChannel) key.channel();
        //创建读取的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //将数据读取到缓冲区
        channel.read(buffer);
        // 4、把缓冲区切换成写出模式
        buffer.flip();
        String rs = new String(buffer.array(),0,buffer.remaining());
        System.out.println(rs);
    }

    public static void main(String[] args) throws IOException {
        NIOServer server = new NIOServer();
        server.initServer(8100);
        server.listen();
    }
}

客户端文章来源地址https://www.toymoban.com/news/detail-838529.html

public class NIOClient {
    //通道管理器
    private Selector selector;

    public static void main(String[] args) throws IOException {
        NIOClient client = new NIOClient();
        client.initClick("127.0.0.1",8100);
        client.listen();
    }
    public void initClick(String ip,int port) throws IOException {
        //获取一个socket
        SocketChannel channel = SocketChannel.open();
        //设置通道为非阻塞
        channel.configureBlocking(false);
        //获取一个通道管理器
        this.selector = Selector.open();

        channel.connect(new InetSocketAddress(ip,port));

        channel.register(this.selector, SelectionKey.OP_CONNECT);
    }

    public void listen() throws IOException {
        while (true){
            selector.select();
            Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                iterator.remove();
                if(key.isConnectable()){
                    SocketChannel channel = (SocketChannel) key.channel();
                    if(channel.isConnectionPending()){
                        channel.finishConnect();
                    }
                    //设置为阻塞
                    channel.configureBlocking(false);
                    //向客户端发送数据源
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    String  message = "服务器端你好,我是客户端";
                    buffer.put(message.getBytes(StandardCharsets.UTF_8));
                    //把缓冲区切换成读取模式
                    buffer.flip();
                    //将buffer写入channel
                    while (buffer.hasRemaining()){
                        channel.write(buffer);
                    }
                    channel.register(this.selector,SelectionKey.OP_READ);
                }else if(key.isReadable()){
                    read(key);
                }
            }
        }
    }

    public void read(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer);
        byte[] data = buffer.array();
        // 4、把缓冲区切换成写出模式
        buffer.flip();
        String rs = new String(data,0,buffer.remaining());
        System.out.println(rs);
    }
}

到了这里,关于NIO核心三:Selector的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JAVA中三种I/O框架——BIO、NIO、AIO

    BIO,同步阻塞IO模型,应用程序发起系统调用后会一直等待数据的请求,直至内核从磁盘获取到数据并拷贝到用户空间; 在一般的场景中,多线程模型下的BIO是成本较低、收益较高的方式。但是,如果在高并发的场景下,过多的创建线程,会严重占据系统资源,降低系统对外

    2024年02月08日
    浏览(54)
  • Java中的三种I/O模型:BIO、NIO和AIO

    I/O(输入/输出)操作是任何应用程序中必不可少的一部分,它涉及到与文件、网络或其他设备之间的数据传输。Java提供了几种不同的I/O模型,其中最常见的是AIO(异步非阻塞I/O)、BIO(阻塞I/O)和NIO(非阻塞I/O)。这些模型在处理I/O操作时具有不同的工作方式、特性和适用

    2024年02月08日
    浏览(38)
  • BIO、NIO和AIO

    目录 一.引言 何为IO IO的过程 Java的3种网络IO模型 阻塞和非阻塞IO IO多路复用 异步和同步IO 二.BIO 三.NIO 1. 三大组件 Channel Buffer Selector 2.ByteBuffer 2.1ByteBuffer的使用 2.2ByteBuffer 结构 ​2.3ByteBuffer的常用方法 分配空间   向 buffer 写入数据 从 buffer 读取数据 字符串与 ByteBuffer 互转 分

    2024年02月12日
    浏览(37)
  • BIO、NIO、AIO区别详解

    主线程发起io请求后,需要等待当前io操作完成,才能继续执行。 引入selector、channel、等概念,当主线程发起io请求后,轮询的查看系统是否准备好执行io操作,没有准备好则主线程不会阻塞会继续执行,准备好主线程会阻塞等待io操作完成。 主线程发起io请求后,不会阻塞,

    2024年02月07日
    浏览(42)
  • BIO、NIO、AIO 的区别

    Java面试题  阻塞IO。一个连接一个线程,当服务端接受到多个客户端的请求时,客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销 同步非阻塞IO 。一个线程处理多个连接。NIO 包含  Channel(通道)、Selector(选择

    2024年01月20日
    浏览(34)
  • BIO、NIO、AIO 有什么区别?

    Java 中的I/O模型主要分为三类:BIO(Blocking I/O)、NIO(New I/O)和AIO(Asynchronous I/O)。它们在处理I/O操作时有着不同的工作方式和特点。 BIO是传统的I/O模型,也称为同步I/O。在BIO中,每个I/O操作都会阻塞线程,直到数据准备好或者操作完成。这意味着一个线程只能处理一个连

    2024年01月16日
    浏览(40)
  • BIO、NIO、AIO 有什么区别

    在Java中,BIO(Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O)都是用于处理I/O(输入/输出)操作的不同方式。它们在处理I/O时具有不同的特点和适用场景。 BIO(Blocking I/O): 阻塞式I/O模型,是Java最传统的I/O模型。 在BIO中,每个I/O操作都会阻塞当前线程,直到操作完

    2024年02月13日
    浏览(35)
  • Java NIO FileChannel:BIO与NIO区别、核心组成部分和常用方方法

    深入探讨Java NIO中的FileChannel,包括BIO与NIO的区别、NIO的核心组成部分(Channels、Buffers、Selectors)、FileChannel的常用方法以及示例代码。了解如何使用FileChannel进行文件数据读写操作。

    2024年01月25日
    浏览(48)
  • NIO核心三:Selector

    选择器提供一种选择执行已经就绪的任务的能力。selector选择器可以让单线程处理多个通道。如果程序打开了多个连接通道,每个连接的流量都比较低,可以使用Selector对通道进行管理。 1.创建Selector 2.必须将通道设置为非阻塞模式才能注册到选择器上 3.把通道注册到选择器上

    2024年03月11日
    浏览(39)
  • BIO、NIO、IO多路复用模型详细介绍&Java NIO 网络编程

    上文介绍了网络编程的基础知识,并基于 Java 编写了 BIO 的网络编程。我们知道 BIO 模型是存在巨大问题的,比如 C10K 问题,其本质就是因其阻塞原因,导致如果想要承受更多的请求就必须有足够多的线程,但是足够多的线程会带来内存占用问题、CPU上下文切换带来的性能问题

    2024年02月14日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包