• Java NIO Test Case


    package org.zwl.test.nio;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.*;
    import java.nio.charset.StandardCharsets;
    import java.util.concurrent.Future;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author zhenweiliu created on 3/6/14
     */
    public class NioServer {
    
        private Selector selector;
        private AtomicInteger acceptCount = new AtomicInteger(0);
        private AtomicInteger readCount = new AtomicInteger(0);
        private AtomicInteger writeCount = new AtomicInteger(0);
    
        public NioServer(int port) throws IOException {
            ServerSocketChannel ssc = ServerSocketChannel.open(); // 使用默认的selector provider生成一个channel
            ssc.configureBlocking(false); // 设置为非阻塞模式
            ssc.bind(new InetSocketAddress(port)); // 绑定到端口
            selector = Selector.open();
            ssc.register(selector, SelectionKey.OP_ACCEPT); // 将channel注册到selector, 并指定其兴趣集事件
    
            while (selector.select() > 0) { // select()是个阻塞方法, 只有当selector中有已经准备好的事件的时候才会返回, 它返回已经准备好的事件数
                for (SelectionKey key : selector.selectedKeys()) { // 遍历已经准备好的事件的key
                    selector.selectedKeys().remove(key);
                    if (key.isAcceptable()) {
                        System.out.println("Accept client " + acceptCount.incrementAndGet());
                        SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                    } else if (key.isReadable()) {
                        System.out.println("Read client " + readCount.incrementAndGet());
                        SocketChannel sc = (SocketChannel) key.channel();
                        ByteBuffer bb = ByteBuffer.allocate(1024);
                        bb.clear();
                        try {
                            while (sc.read(bb) > 0) {
                                bb.flip();
                                System.out.print(StandardCharsets.UTF_8.decode(bb));
                                bb.clear();
                            }
                            System.out.println();
                        } catch (IOException e) {
                            sc.close();
                        }
    
                        if (key.isWritable()) {
                            System.out.println("Write client " + writeCount.incrementAndGet());
                            bb.clear();
                            bb.put("Hello Client".getBytes());
                            bb.flip();
                            try {
                                while (bb.hasRemaining()) {
                                    sc.write(bb);
                                }
                            } catch (Exception e) {
                                sc.close();
                            }
                        }
                    }
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            new NioServer(8089);
        }
    }
    package org.zwl.test.nio;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.StandardCharsets;
    import java.util.Scanner;
    import java.util.concurrent.ExecutionException;
    
    import static java.nio.channels.SelectionKey.OP_CONNECT;
    import static java.nio.channels.SelectionKey.OP_READ;
    import static java.nio.channels.SelectionKey.OP_WRITE;
    
    /**
     * @author zhenweiliu created on 3/6/14
     */
    public class NioClient {
    
        public NioClient(String host, int port) throws Exception {
            Selector selector = Selector.open();
            SocketChannel sc = SocketChannel.open(new InetSocketAddress(host, port));
            sc.configureBlocking(false);
            SelectionKey sk = sc.register(selector, OP_CONNECT | OP_READ | OP_WRITE);
            new ClientWriteThread(sk).start();
            while (selector.select() > 0) {
                for (SelectionKey key : selector.selectedKeys()) {
                    selector.selectedKeys().remove(key);
                    SocketChannel sc2 = (SocketChannel) key.channel();
                    if (key.isConnectable()) {
                        System.out.println("Connection established");
                    } else if (key.isReadable()) {
                        System.out.println("Read Server");
                        ByteBuffer bb = ByteBuffer.allocate(128);
                        bb.clear();
                        while (sc2.read(bb) > 0) {
                            bb.flip();
                            System.out.print(StandardCharsets.UTF_8.decode(bb));
                            bb.clear();
                        }
                        System.out.println();
                    }
                }
            }
        }
    
        private static class ClientWriteThread extends Thread {
    
            private SelectionKey key;
    
            private Scanner scanner = new Scanner(System.in);
    
            public ClientWriteThread(SelectionKey key) {
                this.key = key;
            }
    
            @Override
            public void run() {
                while (key.isWritable()) {
                    String msg = scanner.nextLine();
                    ByteBuffer bb = ByteBuffer.allocate(msg.getBytes().length);
                    bb.clear();
                    bb.put(msg.getBytes());
                    bb.flip();
                    try {
                        while (bb.hasRemaining()) {
                            ((SocketChannel) key.channel()).write(bb);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            new NioClient("localhost", 8089);
    
        }
    }

    使用selector的好处在于

    1. selector可以使用一个线程同时监听多个channel,他们的事件准备由系统通知, 类似于事件驱动, 不需要自己手动缓存所有chanel, 并while去轮询, 这样效率高

    2. 他的read write方法都是非阻塞方法, 返回的是本次操作写入(或读取)成功的数据字节数 

  • 相关阅读:
    Mac下ssh连接远程服务器时自动断开问题
    解决php中json_decode的异常JSON_ERROR_CTRL_CHAR (json_last_error = 3)
    如何写.gitignore只包含指定的文件扩展名
    python操作mysql数据库
    php数组函数
    Python中字符串切片操作
    Python实现字符串反转的几种方法
    每个Android开发者都应该了解的资源列表
    Android Studio 入门指南
    一个优秀的Android应用从建项目开始
  • 原文地址:https://www.cnblogs.com/zemliu/p/3667338.html
Copyright © 2020-2023  润新知