Netty详解(四):Channel介绍

Channel 提供了对网络连接的抽象,通过它你可以执行基本的读写操作,比如读取数据、写入数据、绑定端口等。它还负责触发各种I/O事件,比如连接建立、关闭、读取就绪等。

Channel接口的继承实现关系图
在这里插入图片描述

关注一下SelectableChannel这个接口,它代表了一个可以注册到Selector的通道。这个接口的设计是为了支持多路复用I/O操作,即在一个单独的线程中监控多个通道的I/O活动。

SelectableChannel的主要特点:

  • 选择性:实现SelectableChannel接口的通道可以注册到Selector上,从而可以在单个线程中同时监控多个这样的通道。
  • 阻塞/非阻塞模式:提供了configureBlocking(boolean)方法来控制该通道是否以阻塞还是非阻塞模式工作。
  • 选择键:每个注册到Selector上的SelectableChannel都会关联一个SelectionKey,这个健包含了有关该通道的信息,比如感兴趣的I/O操作类型以及是否准备好进行这些操作。

这里不全部展开,只对FileChannelSocketChannelServerSocketChannelDatagramChannel四种重要的实现做介绍,其中SocketChannelServerSocketChannelDatagramChannel这三个实现了SelectableChannel接口。

  • FileChannel:文件通道,用于文件读写数据。
  • SocketChannel:socket套接字通道,用于客户端套接字TCP连接的数据读写。
  • ServerSocketChannel:服务器套接字通道,允许我们监听TCP连接,为每个监听到的请求创建一个SocketChannel通道。
  • DatagramChannel:UDP连接时的数据报通道。

FileChannel

文件通道,顾名思义,专门操作磁盘文件的通道。需要注意的地方,FileChannel为阻塞模式,不能设置为非阻塞模式。

  1. 获取FileChannel

    // 获取一个文件输入流channel
    FileInputStream fis = new FileInputStream(srcFile);
    FileChannel inChannel = fis.getChannel();
    
    FileOutputStream fos = new FileOutputStream(destFile);
    FileChannel outChannel = fos.getChannel();
    
    // 通过RandomAccessFile(文件随机访问)类来获取FileChannel
    RandomAccessFile rFile = new RandomAccessFile("file.txt", "rw");
    FileChannel channel = rFile.getChannel();
    
  2. 读取FileChannel

    RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
    FileChannel channel = file.getChannel();
    ByteBuffer buf = ByteBuffer.allocate(1024);
    int length = -1;
    while ((length = channel.read(buf)) != -1) {
        // handle buf
    }
    
  3. 写入FileChannel

    // channel写模式下,对于Buffer来说就是读模式,buf就需要翻转一下
    buf.flip();
    int outLength = 0;
    while ((outLength = outChannel.write(buf)) != 0) {
        System.out.println("写入字节数:" + outLength);
    }
    
  4. 关闭通道

    channel.close();
    
  5. 强制刷新到磁盘

    channel.force(true);
    

ServerSocketChennelSocketChannel

在Java NIO中,涉及到网络连接的通道有两个:一个是SocketChannel,负责连接的数据传输;另一个是ServerSocketChannel,负责连接的监听。无论是ServerSocketChannel还是SocketChannel,都支持阻塞和非阻塞两种模式。

socketChannel.configureBlocking(false);
socketChannel.configureBlocking(true);
  1. 获取SocketChannel传输通道

    // 获取一个套接字通道
    SocketChannel socketChannel = SocketChannel.open();
    // 设置为非阻塞模式
    socketChannel.configureBlocking(false);
    // 对服务器的IP和端口发起连接
    socketChannel.connect(new InetSocketAddress("127.0.0.1", 80));
    while (!socketChannel.finishConnect()) {
        // 在连接期间做一些其它事
    }
    
    
    
    // 服务端
    ServerSocketChannel server = (ServerSocketChannel) key.channel();
    SocketChannel socketChannel = server.accept();
    socketChannel.configureBlocking(false);
    
  2. 读取SocketChannel

    ByteBuffer buf = ByteBuffer.allocate(1024);
    int bytesRead = socketChannel.read(buf);
    
  3. 写入SocketChannel

    buffer.flip();
    socketChannel.write(buffer);
    
  4. 关闭SocketChannel

    socketChannel.shutdownOutput();
    IOUtil.closeQuietly(socketChannel);
    

DatagramChannel

DatagramChannel用来处理UDP协议传输协议。

  1. 获取DatagramChannel

    DatagramChannel channel = DatagramChannel.open();
    channel.configureBlocking(false);
    channel.socket().bind(new InetSocketAddress(18080));
    
  2. 读取DatagramChannel

    ByteBuffer buf = ByteBuffer.allocate(1024);
    SocketAddress clientAddr = datagramChannel.receive(buf);
    
  3. 写入DatagramChannel

    buffer.flip();
    channel.send(buffer, new InetSocketAddress("127.0.0.1", 18899));
    buffer.clear();
    
  4. 关闭DatagramChannel

    channel.close();
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨路行人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值