• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

java nio Selector的使用

武飞扬头像
雨橄
帮助1

1、介绍

Selector是nio包的一个抽象类,作为java nio的三大组件(Buffer、Channel,Selector)之一,在java nio网络编程中尤为重要。

Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件,一个Selector可以同时轮询多个Channel,只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。

本文档操作过程中需要使用到Buffer、Channel。

Buffer的使用可参考:http://t.csdn.cn/f1ZB9

Channel的使用可参考:http://t.csdn.cn/0L4Nk

2、代码演示

服务端

public class Server {

    public static void main(String[] args) throws IOException {
        ServerSocketChannel server = ServerSocketChannel.open();
        //监听8080端口
        server.bind(new InetSocketAddress(8080));

        //ServerSocketChannel必须设置为非阻塞模式,否则无法绑定Selector对象
        server.configureBlocking(false);

        Selector selector = Selector.open();

        //将连接到达事件注册到Selector对象上
        server.register(selector, SelectionKey.OP_ACCEPT);

        //select()为阻塞方法,当有注册到Selector对象上的事件被触发时,select()方法将有返回值
        while (selector.select()>0){
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keys.iterator();

            while (iterator.hasNext()){
                SelectionKey key = iterator.next();

                if(key.isAcceptable()){
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel channel = serverChannel.accept();
                    channel.configureBlocking(false);

                    //将数据可读事件注册到Selector对象上
                    channel.register(selector,SelectionKey.OP_READ);
                }else if(key.isReadable()){
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(100);

                    while (true){
                        int num = channel.read(buffer);
                        if (num>0){
                            buffer.flip();
                            byte[] bytes = new byte[num];
                            buffer.get(bytes);

                            //处理读取Channel中读取到的数据
                            handMsg(channel,bytes);
                        }else if(num==0){
                            //已经读取到数据末尾,无数据可读
                            break;
                        }else if(num<0){
                            //num=-1,tcp客户端断开连接
                            closeIO(channel);
                            break;
                        }
                        buffer.clear();
                    }
                }
                iterator.remove();
            }
        }
    }

    /**
     * 新建线程异步处理SocketChannel中读取到的字节数组
     * @param channel
     * @param arr
     */
    private static void handMsg(SocketChannel channel,byte[] arr){
        new Thread(()->{
            ByteBuffer buffer = ByteBuffer.wrap(arr);
            try {
                //写数据到Channel,返回数据给tcp客户端
                channel.write(buffer);
            } catch (Exception e) {
                closeIO(channel);
                e.printStackTrace();
            }
        }).start();
    }

    //关闭流方法
    private static void closeIO(Closeable io){
        if(io!=null){
            try{
                io.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakjfb
系列文章
更多 icon
同类精品
更多 icon
继续加载