• aio,nio ,io 心得


    1.nio 流的过程有几个,连接,可读,读 ,返回 ;连接了不一定可读,等待浪费时间,这些时间可以去读其他的连接,selector是管理,管理全部测一下可不可读,只对可读的连接进行读取。同时,nio有缓冲区,可以一大勺一大勺的吃饭,io是一粒米一粒米的

    2.aio的话就是可以读了就回调方法,不是直接走方法,是异步的;

    3.io之前就是一直等

     public class SelectorServer {
     
        public static void main(String[] args) throws IOException {
            Selector selector = Selector.open();
     
            ServerSocketChannel server = ServerSocketChannel.open();
            server.socket().bind(new InetSocketAddress(8080));
     
            // 将其注册到 Selector 中,监听 OP_ACCEPT 事件
            server.configureBlocking(false);
            server.register(selector, SelectionKey.OP_ACCEPT);
     
            while (true) {
                // 需要不断地去调用 select() 方法获取最新的准备好的通道
                int readyChannels = selector.select();
                if (readyChannels == 0) {
                    continue;
                }
                Set<SelectionKey> readyKeys = selector.selectedKeys();
                // 遍历
                Iterator<SelectionKey> iterator = readyKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
     
                    if (key.isAcceptable()) {
                        // 有已经接受的新的到服务端的连接
                        SocketChannel socketChannel = server.accept();
     
                        // 有新的连接并不代表这个通道就有数据,
                        // 这里将这个新的 SocketChannel 注册到 Selector,监听 OP_READ 事件,等待数据
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        // 有数据可读
                        // 上面一个 if 分支中注册了监听 OP_READ 事件的 SocketChannel
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                        int num = socketChannel.read(readBuffer);
                        if (num > 0) {
                            // 处理进来的数据...
                            System.out.println("收到数据:" + new String(readBuffer.array()).trim());
                            socketChannel.register(selector, SelectionKey.OP_WRITE);
                        } else if (num == -1) {
                            // -1 代表连接已经关闭
                            socketChannel.close();
                        }
                    }
                    else if (key.isWritable()) {
                        // 通道可写
                        // 给用户返回数据的通道可以进行写操作了
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.wrap("返回给客户端的数据...".getBytes());
                        socketChannel.write(buffer);
     
                        // 重新注册这个通道,监听 OP_READ 事件,客户端还可以继续发送内容过来
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                }
            }
        }
    }

    aio

    package com.javadoop.aio;
     
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
     
    public class Server {
     
        public static void main(String[] args) throws IOException {
     
              // 实例化,并监听端口
            AsynchronousServerSocketChannel server =
                    AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));
     
            // 自己定义一个 Attachment 类,用于传递一些信息
            Attachment att = new Attachment();
            att.setServer(server);
     
            server.accept(att, new CompletionHandler<AsynchronousSocketChannel, Attachment>() {
                @Override
                public void completed(AsynchronousSocketChannel client, Attachment att) {
                    try {
                        SocketAddress clientAddr = client.getRemoteAddress();
                        System.out.println("收到新的连接:" + clientAddr);
     
                        // 收到新的连接后,server 应该重新调用 accept 方法等待新的连接进来
                        att.getServer().accept(att, this);
     
                        Attachment newAtt = new Attachment();
                        newAtt.setServer(server);
                        newAtt.setClient(client);
                        newAtt.setReadMode(true);
                        newAtt.setBuffer(ByteBuffer.allocate(2048));
     
                        // 这里也可以继续使用匿名实现类,不过代码不好看,所以这里专门定义一个类
                        client.read(newAtt.getBuffer(), newAtt, new ChannelHandler());
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
     
                @Override
                public void failed(Throwable t, Attachment att) {
                    System.out.println("accept failed");
                }
            });
            // 为了防止 main 线程退出
            try {
                Thread.currentThread().join();
            } catch (InterruptedException e) {
            }
        }
    }
    package com.javadoop.aio;
     
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.CompletionHandler;
    import java.nio.charset.Charset;
     
    public class ChannelHandler implements CompletionHandler<Integer, Attachment> {
     
        @Override
        public void completed(Integer result, Attachment att) {
            if (att.isReadMode()) {
                // 读取来自客户端的数据
                ByteBuffer buffer = att.getBuffer();
                buffer.flip();
                byte bytes[] = new byte[buffer.limit()];
                buffer.get(bytes);
                String msg = new String(buffer.array()).toString().trim();
                System.out.println("收到来自客户端的数据: " + msg);
     
                // 响应客户端请求,返回数据
                buffer.clear();
                buffer.put("Response from server!".getBytes(Charset.forName("UTF-8")));
                att.setReadMode(false);
                buffer.flip();
                // 写数据到客户端也是异步
                att.getClient().write(buffer, att, this);
            } else {
                // 到这里,说明往客户端写数据也结束了,有以下两种选择:
                // 1. 继续等待客户端发送新的数据过来
    //            att.setReadMode(true);
    //            att.getBuffer().clear();
    //            att.getClient().read(att.getBuffer(), att, this);
                // 2. 既然服务端已经返回数据给客户端,断开这次的连接
                try {
                    att.getClient().close();
                } catch (IOException e) {
                }
            }
        }
     
        @Override
        public void failed(Throwable t, Attachment att) {
            System.out.println("连接断开");
        }
    }
    

      

  • 相关阅读:
    Win7旗舰版中的IIS配置asp.net的运行环境
    jquery $(document).ready() 与window.onload的区别
    DEFAULT CURRENT_TIMESTAMP
    存储过程 跳出
    rabbitMQ 重试
    oracle update left join 写法
    error: snap "eclipse" has "install-snap" change in progress
    数据库去空格 去table 去回车符号 去重
    分组 拼接字段
    msyql 去重
  • 原文地址:https://www.cnblogs.com/dzhou/p/10490526.html
Copyright © 2020-2023  润新知