美文网首页
Netty 源码分析 —— NIO 基础(二)之 Channel

Netty 源码分析 —— NIO 基础(二)之 Channel

作者: 小安的大情调 | 来源:发表于2020-02-10 22:51 被阅读0次

    我准备战斗到最后,不是因为我勇敢,是我想见证一切。 --双雪涛《猎人》

    [TOC]
    Thinking

    1. 一个技术,为什么要用它,解决了那些问题?
    2. 如果不用会怎么样,有没有其它的解决方法?
    3. 对比其它的解决方案,为什么最终选择了这种,都有何利弊?
    4. 你觉得项目中还有那些地方可以用到,如果用了会带来那些问题?
    5. 这些问题你又如何去解决的呢?

    本文基于Netty 4.1.45.Final-SNAPSHOT

    1、简述

    ​ Channel是JDK 1.4之后引入的NIO中非常重要的一个概念,所有的I/O操作必须通过Channel进行读写,不能直接操作缓冲区Buffer。(这里需要提醒的一点就是,Channel是双向的,既可以从通道中读取数据,又可以写数据到通道。)

    那么Java NIO 中的通道(Channel)于传统BIO中的文件流有那些异同呢?

    • Channel即可以读取数据,又可以向里写数据。但是流的读写通常是单向的。
    • 通道可以异步地读写。
    • 通道中地数据总是要先读到一个Buffer中,或者总是要从一个Buffer中写入。

    上述操作如图所示:


    Channel通道双向读写数据.png

    2、Channel

    java.nio.channels.Channel

    2.1、源码

    public interface Channel extends Closeable {
    
        /**
         * Tells whether or not this channel is open.
            判断此通道是否处于打开状态
         *
         * @return <tt>true</tt> if, and only if, this channel is open
         */
        public boolean isOpen();
    
        /**
         * Closes this channel.
            关闭此通道
         *
         * <p> After a channel is closed, any further attempt to invoke I/O
         * operations upon it will cause a {@link ClosedChannelException} to be
         * thrown.
         *关闭通道后,
            任何进一步尝试在其上调用I / O 的操作都会导致抛出{@link ClosedChannelException}
    
         * <p> If this channel is already closed then invoking this method has no
         * effect.
            如果此通道已关闭,则调用此方法无效
         *
         * <p> This method may be invoked at any time.  If some other thread has
         * already invoked it, however, then another invocation will block until
         * the first invocation is complete, after which it will return without
         * effect. </p>
            可以随时调用此方法。但是,如果某个其他线程已经调用了它,
            则另一个调用将被阻塞,直到第一个调用完成为止,之后它将返回而没有任何效果
            
            就是在该Method 调用后,还是可以被调用的,但是如果此方法正在被调用,该操作是会被阻塞的。
            之后调用不会返回任何东西。
    
         *
         * @throws  IOException  If an I/O error occurs
         */
        public void close() throws IOException;
    
    }
    

    ​ Channel有非常多的实现,其中有四个非常重要的类

    2.2、类图

    Channel类图.png
    • FileChannel :从文件中读写数据。
    • DatagramChannel :通过UDP读写网络中的数据。
    • SocketChannel :通过TCP读写网络中的数据。
    • ServerSocketChannel : 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

    2.3、示例

    /**
     * Channel 示例
     * <p>
     * 使用FileChannel 读取文件 基于Buffer
     *
     * @author by Mr. Li
     * @date 2020/2/10 22:08
     */
    @Slf4j
    public class ChannelExample {
        public static void main(String[] args) throws Exception {
            RandomAccessFile file = new RandomAccessFile("E:/idea_workspace/springcloud2.0/netty/netty-mytest/src/main/resources/data/nio-data.txt", "rw");
            FileChannel channel = file.getChannel();
    
            // 获取 缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
    
            int read = channel.read(buf);
            while (read != -1) {
                log.info("Read Ended ,Message:{}", read);
    
                // 数组反转,才能读取
                buf.flip();
                while (buf.hasRemaining()) {
                    log.info("Message:{}", buf.get());
                }
    
                // 清空缓冲区
                buf.clear();
                read = channel.read(buf);
            }
            file.close();
        }
    
    }
    

    本文仅供笔者本人学习,一起进步!

    ——努力努力再努力xLg

    加油!

    相关文章

      网友评论

          本文标题:Netty 源码分析 —— NIO 基础(二)之 Channel

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