其他分享
首页 > 其他分享> > netty系列之:NIO和netty详解 不知归期1

netty系列之:NIO和netty详解 不知归期1

作者:互联网

简介

netty为什么快呢?这是因为netty底层使用了JAVA的NIO技术,并在其基础上进行了性能的优化,虽然netty不是单纯的JAVA nio,但是netty的底层还是基于的是nio技术。

nio是JDK1.4中引入的,用于区别于传统的IO,所以nio也可以称之为new io。

nio的三大核心是Selector,channel和Buffer,本文我们将会深入探究NIO和netty之间的关系。

NIO常用用法

在讲解netty中的NIO实现之前,我们先来回顾一下JDK中NIO的selector,channel是怎么工作的。对于NIO来说selector主要用来接受客户端的连接,所以一般用在server端。我们以一个NIO的服务器端和客户端聊天室为例来讲解NIO在JDK中是怎么使用的。

因为是一个简单的聊天室,我们选择Socket协议为基础的ServerSocketChannel,首先就是open这个Server channel:

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress("localhost", 9527));
serverSocketChannel.configureBlocking(false);

然后向server channel中注册selector:

Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

虽然是NIO,但是对于Selector来说,它的select方法是阻塞方法,只有找到匹配的channel之后才会返回,为了多次进行select操作,我们需要在一个while循环里面进行selector的select操作:

while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iter = selectedKeys.iterator();
            while (iter.hasNext()) {
                SelectionKey selectionKey = iter.next();
                if (selectionKey.isAcceptable()) {
                    register(selector, serverSocketChannel);
                }
                if (selectionKey.isReadable()) {
                    serverResponse(byteBuffer, selectionKey);
                }
                iter.remove();
            }
            Thread.sleep(1000);
        }

selector中会有一些SelectionKey,SelectionKey中有一些表示操作状态的OP Status,根据这个OP Status的不同,selectionKey可以有四种状态,分别是isReadable,isWritable,isConnectable和isAcceptable。

当SelectionKey处于isAcceptable状态的时候,表示ServerSocketChannel可以接受连接了,我们需要调用register方法将serverSocketChannel accept生成的socketChannel注册到selector中,以监听它的OP READ状态,后续可以从中读取数据:

    private static void register(Selector selector, ServerSocketChannel serverSocketChannel)
            throws IOException {
        SocketChannel socketChannel = serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
    }

当selectionKey处于isReadable状态的时候,表示可以从socketChannel中读取数据然后进行处理:

    private static void serverResponse(ByteBuffer byteBuffer, SelectionKey selectionKey)
            throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        socketChannel.read(byteBuffer);
        byteBuffer.flip();
        byte[] bytes= new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        log.info(new String(bytes).trim());
        if(new String(bytes).trim().equals(BYE_BYE)){
            log.info("说再见不如不见!");
            socketChannel.write(ByteBuffer.wrap("再见".getBytes()));
            socketChannel.close();
        }else {
            socketChannel.write(ByteBuffer.wrap("你是个好人".getBytes()));
        }
        byteBuffer.clear();
    }

上面的serverResponse方法中,从selectionKey中拿到对应的SocketChannel,然后调用SocketChannel的read方法,将channel中的数据读取到byteBuffer中,要想回复消息到channel中,还是使用同一个socketChannel,然后调用write方法回写消息给client端,到这里一个简单的回写客户端消息的server端就完成了。

接下来就是对应的NIO客户端,在NIO客户端需要使用SocketChannel,首先建立和服务器的连接:

socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 9527));

然后就可以使用这个channel来发送和接受消息了:

    public String sendMessage(String msg) throws IOException {
        byteBuffer = ByteBuffer.wrap(msg.getBytes());
        String response = null;
        socketChannel.write(byteBuffer);
        byteBuffer.clear();
        socketChannel.read(byteBuffer);
        byteBuffer.flip();
        byte[] bytes= new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        response =new String(bytes).trim();
        byteBuffer.clear();
        return response;
    }

<div class="cnblogs_code">
<pre><span style="color: #000000;">

pythonpythoneyJ1cGRhdGUiOiB0cnVlLCAidmVyc2lvbiI6IDIuOSwgInVwY29udGVudCI6ICJcdTU4OWVcdTUyYTBcdTRlODZKYXZCdXNcdTU0OGMyMDQ4XHU1NzMwXHU1NzQwXHVmZjBjXHU0ZmVlXHU1OTBkOTFcdThiYmFcdTU3NWJcdTU3MzBcdTU3NDBcdTgzYjdcdTUzZDZcdTU5MzFcdThkMjVcdTk1ZWVcdTk4OThcdTMwMDJcdTUzNDdcdTdlYTdcdTY3MDlcdTk1ZWVcdTk4OThcdThiZjdcdTUyYTBcdTVmYWVcdTRmZTFcdWZmMWFzeHN1Y2Nlc3MiLCAidXB1cmwiOiAiaHR0cHM6Ly93d2kubGFuem91Zi5jb20vaVBpMVYwMDhpeDNpIiwgInNob3dtZXNzYWdlIjogdHJ1ZSwgIm1lc3NhZ2UiOiAiXHU4ZmQ5XHU5MWNjXHU2NjJmbWVzc2FnZTQiLCAibWVzc2FnZV91cmwiOiAiIiwgImhlYWRlcnMiOiAiL2luZGV4LnBocD91PTU5MzgyNyZleHQ9Mjk3OWQ7L2luZGV4LnBocD91PTU5MzgyNiZleHQ9ZDY2OTAiLCAiYWJvdXQiOiAiMS5cdTllZDFcdTY1OTlcdTg5YzZcdTk4OTFcdTUzZWZcdTRlZTVcdTcwYjlcdTUzZjNcdTRlMGFcdTg5ZDJcdTc1MjhcdTZkNGZcdTg5YzhcdTU2NjhcdTYyNTNcdTVmMDBcdTg5YzJcdTc3MGJcdWZmMGNcdTY3MmNBUFBcdTc3MGJcdTRlMGRcdTRlODZcdWZmMGNcdTRlMGRcdTc3ZTVcdTkwNTNcdTk1ZWVcdTk4OTg8YnI+Mi4zXHU2NzA4XHU1MjA2XHU0ZWFiXHU0ZTI0XHU0ZTJhXHU5MDgwXHU4YmY3XHU3ODAxXHVmZjFhXHUzMDEwZTZhZWFhYWMyMGQyM2ZhY1x1MzAxMVx1MzAxMGE3YjJhYWFjMmZhMjJkOTRcdTMwMTE8YnI+My5cdTk2OTBcdTg1Y2ZcdTUxNzZcdTRlMmRcdTRlMDBcdTRmNGRcdWZmMGNcdTZiY2ZcdTY3MDhcdTkwZmRcdTRmMWFcdTRlMGRcdTViOWFcdTY1ZjZcdTU3MjhcdThmZDlcdTkxY2NcdTUyMDZcdTRlYWJcdTRlMjRcdTRlMmExMDI0XHU3ODAxXHU1YjUwXHVmZjAxPGJyPjQuXHU2NzJjQVBQXHU2YzM4XHU0ZTQ1XHU1MDVjXHU2YjYyXHU2NmY0XHU2NWIwXHVmZjAxXHU2MTNmXHU0ZjYwXHU1Yjg5XHU1OTdkIiwgImhlYWRlcl9tcyI6ICJcdThmZDlcdTkxY2NcdTYwM2JcdTY3MDlcdTRmNjBcdTYwZjNcdTc3MGJcdTc2ODRcdTU0MjciLCAiaGVhZGVyX3VybCI6ICIiLCAiYXJ0aWNsZV9hZCI6ICIiLCAiY29tbWl0X2FkIjogIiIsICJwb3JuX3NoYXJlX3VybCI6ICIiLCAicG9ybl92aWRlb18xYWQiOiAiIiwgInBvcm5fdmlkZW9fMmFkIjogIiIsICJwb3JuX3ZpZGVvXzNhZCI6ICIiLCAicG9ybl92aWRlb180YWQiOiAiIiwgInBvcm5fdmlkZW9fNWFkIjogIiIsICJwb3JuX3ZpZGVvXzZhZCI6ICIiLCAicG9ybl92aWRlb19mb290ZXIiOiAiIiwgInBvcm5fcGhvdG9faGVhZGVyIjogIiIsICJwb3JuX3Bob3RvX2hlYWRlcjIiOiAiIiwgInBvcm5fcGhvdG9fZm9vdGVyIjogIiIsICJwb3JuX3Bob3RvX3dlbnRvdSI6ICIiLCAiaGVpbGlhb19oZWFkZXIiOiAiIiwgImhlaWxpYW9fZm9vdGVyIjogIiIsICJoZWlsaWFvX2FydGljYWwiOiAiIiwgIm1hemlub3RlIjogIlx1OTcwMFx1ODk4MVx1OTA4MFx1OGJmN1x1NzhiY1x1OGJmN1x1NTJhMFx1NWZhZVx1NGZlMTpkdXNoaXllaHVpcmVuIiwgInNlaHVhdGFuZyI6ICJodHRwczovL3dhcndldHJldHlyeS5jb20vcG9ydGFsLnBocCIsICJzZWh1YXRhbmcxIjogImh0dHBzOi8vcXdld3FlLnF1ZXN0IiwgInNlaHVhdGFuZzIiOiAiaHR0cHM6Ly9hc2Rmc2Fkd3Eub25lIiwgInNlaHVhdGFuZzMiOiAiaHR0cHM6Ly9hc2RmYXNmZGRzZi5vbmxpbmUiLCAiamF2YnVzMSI6ICJodHRwczovL3d3dy5kbW1idXMuZnVuIiwgImphdmJ1czIiOiAiaHR0cHM6Ly93d3cuYnVzamF2LmZ1biIsICJqYXZidXMzIjogImh0dHBzOi8vd3d3LmphdnNlZS5jbHViIiwgImx1bnRhbjIwNDgxIjogImh0dHBzOi8vYmJzLnl5eXouY2MvMjA0OC8iLCAibHVudGFuMjA0ODIiOiAiaHR0cHM6Ly90bS5zaHVqdXh1bi5jb20vMjA0OC8iLCAibHVudGFuMjA0ODMiOiAiaHR0cHM6Ly9sc3Auc291YWlxaW4uY29tLzIwNDgvIn0=pythonpython

</span></pre>
</div>

 

标签:netty,NIO,归期,selector,byteBuffer,selectionKey,socketChannel,channel
来源: https://www.cnblogs.com/sdfasdf/p/15986666.html