NIO 之 selector 原理

本文深入探讨了Java NIO中的Selector机制,通过SelectorServerChannel和SelectorClientChannel两个类的实现,详细解析了服务器如何使用Selector监听多个客户端的连接请求,并处理读写操作。同时,客户端如何连接服务器并进行数据交互的过程也被清晰地阐述。
摘要由CSDN通过智能技术生成
SelectorServerChannel 类: 

public class SelectorServerChannel {

    private Selector selector;

    private ServerSocketChannel serverSocketChannel = null;

    private int keys = 0 ;

    public static void main(String[] args) {
        new SelectorServerChannel().start();
    }

    private void start() {
        try {
            SelectorServerChannel selectorServerChannel = new SelectorServerChannel();

            // 1- 启动服务
            selectorServerChannel.initServer();

            // 2- 监听
            selectorServerChannel.listen();

        } catch (Exception e) {

        }

    }

    private void listen() throws Exception {
        System.out.println("服务器已经启动成功......");
        while (true){
            keys = selector.select();
            if ( keys > 0 ) {
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while ( iterator.hasNext() ){
                    SelectionKey key = iterator.next();
                    iterator.remove();

                    //处理
                    processHander(key);

                }

            }
        }
    }

    private void processHander(SelectionKey key) throws  Exception{
        if ( null == key ) {
            return;
        }
        if ( key.isAcceptable() ) {
            processAccept(key);
        }
        if ( key.isReadable() ) {
            processRead(key);
        }

    }

    private void processRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();

        // 缓冲区
        ByteBuffer buff = ByteBuffer.allocate(1024);
        CharBuffer charBuff = CharBuffer.allocate(1024);
        buff.clear();
        int len = channel.read(buff);

        String msg = "服务器收到信息: " + new String(buff.array(),0,len);
        buff.flip();
        System.out.println(msg);

    }

    private void processAccept(SelectionKey key) throws IOException {
        serverSocketChannel = (ServerSocketChannel) key.channel();

        // 获取和客户端连接的通道
        SocketChannel channel = serverSocketChannel.accept();

        // 给客户端通道设置为非阻塞
        channel.configureBlocking(false);

        ByteBuffer buffer = ByteBuffer.wrap("欢迎你连接".getBytes());
        channel.write(buffer);

        //把客户端通道注册到selector
        channel.register(selector,SelectionKey.OP_READ);
    }

    private void initServer() throws IOException {

        //1- 打开一个通道
        serverSocketChannel = ServerSocketChannel.open();

        // 2- 获取选择器
        selector = Selector.open();

        // 3- 绑定通道的端口号
        serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1",8888));

        // 4- 设置通道为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 5- 注册这个通道
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    }

}

 

SelectorClientChannel 类:

public class SelectorClientChannel {


    private Selector selector;

    private ByteBuffer outBuff = ByteBuffer.allocate(1024);
    private CharBuffer outCharBuff = CharBuffer.allocate(1024);

    private ByteBuffer inBuff = ByteBuffer.allocate(1024);
    private CharBuffer inCharBuff = CharBuffer.allocate(1024);

    private int keys = 0 ;
    private SocketChannel channel = null;

    public static void main(String[] args) throws IOException {
        new SelectorClientChannel().start();
    }

    private void start() throws IOException {
        initClient();
        listen();
    }

    private void listen() throws IOException {
        while (true){

            keys = selector.select();
            if ( keys > 0 ) {
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while(iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    // 处理
                    processHander(key);
                }
            }
        }

    }

    private void processHander(SelectionKey key) throws IOException {
        if ( key.isConnectable() ) {

            SocketChannel channel = (SocketChannel) key.channel();
            if ( channel.isConnectionPending() ) {
                channel.finishConnect();
                System.out.println("完成连接!");
            }
            channel.register(selector,SelectionKey.OP_WRITE);
        }
        if ( key.isWritable() ) {
            SocketChannel channel = (SocketChannel) key.channel();
            outBuff.clear();
            System.out.println("客户端正在写数据...");
            outBuff = ByteBuffer.wrap("我是Tom1".getBytes());
            channel.write(outBuff);
            channel.register(selector,SelectionKey.OP_READ);
            System.out.println("客户端写数据完成。");
        }
        if ( key.isReadable() ) {
            SocketChannel channel = (SocketChannel) key.channel();
            inBuff.clear();
            System.out.println("客户端正在读数据...");
            int len = channel.read(inBuff);
            System.out.println(">>>>>" + new String(inBuff.array(),0,len));
            System.out.println("客户端读取数据完成!");
        }
    }

    private void initClient() throws IOException {
        //1- 获取一个socket通道,
        channel = SocketChannel.open();

        //2- 获取一个选择器
        selector = Selector.open();

        //3- 通道设置为非阻塞
        channel.configureBlocking(false);

        //4- 连接服务器
        //channel.socket().connect(new InetSocketAddress("127.0.0.1",8888));
        channel.connect(new InetSocketAddress("127.0.0.1",8888));

        //4- 注册通道
        channel.register(selector, SelectionKey.OP_CONNECT);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值