ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-03-09 19:31:43  阅读:205  来源: 互联网

标签:netty NIO 归期 selector byteBuffer selectionKey socketChannel channel


简介

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有