美文网首页技术栈
2019-05-11——Java NIO Socket

2019-05-11——Java NIO Socket

作者: 烟雨乱平生 | 来源:发表于2019-05-13 11:38 被阅读0次

    NIO的出现使得传统的Socket的通讯发生了巨大的改变。

    NIO本质就是避免原始的TCP建立连接使用的3次握手的操作,减少网络开销。

    NIO是非阻塞的

    相比于传统的阻塞型IO,NIO是非阻塞的,所以对于服务端有如下做法:

    /*使用NIO非阻塞处理socket请求*/
    public static void s5() throws IOException {
        ExecutorService threadPool = new ThreadPoolExecutor(10,50,60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(9999));
        while (true){
            System.out.println("等待客户端接入...");
            SocketChannel socketChannel = serverSocketChannel.accept();
            if(socketChannel==null){
                continue;
            }
            threadPool.execute(()->{
                try {
                    clientJoin();
                    read(socketChannel);
                    socketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
    
    private static void read(SocketChannel socketChannel) throws IOException {
        StringBuilder content = new StringBuilder();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        while(socketChannel.read(byteBuffer)!=-1){
            byteBuffer.flip();
            while (byteBuffer.hasRemaining()){
                byte[] data = new byte[byteBuffer.remaining()];
                byteBuffer.get(data);
                content.append(new String(data,0,data.length));
            }
            byteBuffer.clear();
        }
        System.out.println(content.toString());
    }
    

    当然也可以使用著名的Reactoer模式

    服务端

    /*Reactor模型*/
    public static void s6() throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(9999));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (selector.select()>0){
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isConnectable()){
                    onConnection(selectionKey);
                }else if(selectionKey.isAcceptable()){
                    onAccept(selectionKey);
                }else if(selectionKey.isReadable()){
                    onRead(selectionKey);
                }else if(selectionKey.isWritable()){
                    onWrite(selectionKey);
                }
                iterator.remove();
            }
        }
    }
    
    private static void onWrite(SelectionKey selectionKey) throws IOException {
        System.out.println("写就绪");
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        write(channel);
        channel.close();
    }
    
    private static void onRead(SelectionKey selectionKey) throws IOException {
        System.out.println("读就绪");
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        read(channel);
        channel.register(selectionKey.selector(),SelectionKey.OP_WRITE);
    }
    
    private static void onAccept(SelectionKey selectionKey) throws IOException {
        System.out.println("接收数据就绪");
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
        SocketChannel socketChannel = serverSocketChannel.accept();
        Selector selector = selectionKey.selector();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector,SelectionKey.OP_READ);
    }
    
    private static void onConnection(SelectionKey selectionKey) {
        System.out.println("链接就绪");
    }
    
    private static void read(SocketChannel socketChannel) throws IOException {
        StringBuilder content = new StringBuilder();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        while(socketChannel.read(byteBuffer)!=-1){
            byteBuffer.flip();
            while (byteBuffer.hasRemaining()){
                byte[] data = new byte[byteBuffer.remaining()];
                byteBuffer.get(data);
                content.append(new String(data,0,data.length));
            }
            byteBuffer.clear();
        }
        System.out.println(content.toString());
    }
    
    private static void write(SocketChannel socketChannel) throws IOException {
        byte[] data = "这是服务端,正在使用Channel".getBytes();
        ByteBuffer byteBuffer = ByteBuffer.allocate(data.length);
        byteBuffer.put(data);
        byteBuffer.flip();
        socketChannel.write(byteBuffer);
    }
    

    相关文章

      网友评论

        本文标题:2019-05-11——Java NIO Socket

        本文链接:https://www.haomeiwen.com/subject/nudfaqtx.html