zoukankan      html  css  js  c++  java
  • Java NIO工作原理

    数据通信流程:
    通过selector.select()阻塞方法获取到感兴趣事件的key,根据key定位到channel,通过channel的读写操作进行数据通信。channel的read或者write操作都是通过buffer进行的。

    代码示例

    Server:

    public class Server {
        public static void main(String[] args) throws InterruptedException {
            final int port = 9999;
            try {
                // 初始化server
                ServerSocketChannel server = ServerSocketChannel.open();
                server.socket().bind(new InetSocketAddress(port));
                Selector selector = Selector.open();
    
                // 这一步的设置在register中需要用到,所以要在register之前设置,否则会发生异常
                server.configureBlocking(false);
                SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT);
    
    
                ByteBuffer buffer = ByteBuffer.allocate(50);
                // 事件循环
                while(true) {
                    Thread.sleep(500);
                    selector.select();
                    Set<SelectionKey> keys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = keys.iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (!key.isValid()) {
                            continue;
                        }
                        if (key.isAcceptable()) {
                            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                            SocketChannel sc = ssc.accept();
                            sc.configureBlocking(false);
                            sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
    //                        System.out.println(serverKey == key);
                            continue;
                        }
                        if (key.isReadable()) {
                            SocketChannel sc = (SocketChannel) key.channel();
                            sc.read(buffer);
                            buffer.flip();
                            System.out.println(new String(buffer.array(), 0, buffer.limit()));
                        }
                        if (key.isWritable()) {
                            SocketChannel sc = (SocketChannel) key.channel();
                            sc.write(ByteBuffer.wrap("I am server!".getBytes()));
                        }
                    }
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    Client:

    public class Client {
        public static void main(String[] args) throws IOException, InterruptedException {
            SocketChannel client = SocketChannel.open();
            client.connect(new InetSocketAddress("localhost", 9999));
            client.configureBlocking(false);
    
            ByteBuffer buffer = ByteBuffer.allocate(50);
            while (true) {
                buffer.clear();
                int i = client.read(buffer);
                if (i > 0) {
                    buffer.flip();
                    System.out.println(new String(buffer.array(), 0, buffer.limit()));
                }
    
                client.write(ByteBuffer.wrap("I am a client!".getBytes()));
                Thread.sleep(500);
            }
        }
    }
    

    其他

    运行在Linux kernel 2.6以后的OS中的Java应用,NIO的底层实现是根据OS提供的io多路复用接口epoll实现。

    参考资料

  • 相关阅读:
    c#对XML读取
    WPF--TypeConverter使用
    WPF---对于没有Command属性的添加以下代码可以达到有Command效果
    自定义事件、属性、方法
    读取Excel文件
    ClickOnce安装部署,手动。
    Logger 日志记录
    Maven
    等待与通知范式
    线程状态及基本方法
  • 原文地址:https://www.cnblogs.com/liushijie/p/5429046.html
Copyright © 2011-2022 走看看