javaNIO入门篇——Selector的使用

selector 一般称 为选择器 ,它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写等,可以实现单线程管理多个channels,也就是可以管理多个网络链接。

1.阻塞式,不使用用selector,和传统BIO 一样,当有多个客户端链接时,服务端需要开启多线程,
在这里插入图片描述
2.非阻塞式,当有多个客户端链接时,服务器只需要开启一个线程

在这里插入图片描述

selector的使用案例


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;

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocketChannel sschannel = ServerSocketChannel.open();
            sschannel.bind(new InetSocketAddress(10086));
            System.out.println("server is running at"+sschannel.getLocalAddress());
            sschannel.configureBlocking(false);
            //获取选择器
            Selector selector = Selector.open();
            //将通道注册到选测器,指定接受“监听事件”
            sschannel.register(selector, SelectionKey.OP_ACCEPT);
            while (selector.select()>0){
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while (it.hasNext()){
                    //获取准备就绪的事件
                    SelectionKey sk  =it.next();
                    //判断是什么事件就绪
                    if(sk.isAcceptable()){
                        //若是接受就绪,就获取客户端链接
                        SocketChannel schannel = sschannel.accept();
                        System.out.println("client"+schannel.getRemoteAddress()+" has connected");
                        schannel.configureBlocking(false);
                        schannel.register(selector,SelectionKey.OP_READ);
                    }else if(sk.isReadable()){
                        //获取当前选择器上“读就绪”状态的通道
                        SocketChannel socketChannel = (SocketChannel) sk.channel();
                        //读数据
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int len =0;
                        while ((len = socketChannel.read(buffer))>0){
                            buffer.flip();
                            System.out.println("["+socketChannel.getRemoteAddress()+"]:"+new String(buffer.array(),0,len));

                        buffer.clear();
                        }
                    }
                    //取消选择建
                    it.remove();
                }
            }
            sschannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;

public class Client1 {
    public static void main(String[] args) {
        try {
            //1.建立SocketChannel
            SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",10086));
            //2.设置非阻塞模式
            socketChannel.configureBlocking(false);
            //3.分配缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            //4.发送数据给服务端
            Scanner scanner = new Scanner(System.in);
            String str = null;
            while (!"quit".equals(str)){
                System.out.println("请说:");
                str= scanner.nextLine();
                byteBuffer.put((str+"   "+printTime3(null)).getBytes());
                byteBuffer.flip();
                socketChannel.write(byteBuffer);
                byteBuffer.clear();
            }
            socketChannel.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 按格式输出当前时间
     * @param pattern 时间格式,如HH:mm:ss    yyyyy-MM-dd
     * @return 格式化后的时间字符串
     */
    public  static  String printTime3(@Nullable String pattern){
        String pat = "yyyy-MM-dd HH:mm:ss";
        if(pattern==null||"".equals(pattern)) {
            pattern = pat;
        }
        LocalDateTime ldt  = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return formatter.format(ldt);
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述

发布了17 篇原创文章 · 获赞 2 · 访问量 677

猜你喜欢

转载自blog.csdn.net/qq_43615903/article/details/104168226