美文网首页
第 4 章 传输

第 4 章 传输

作者: FaDeo_O | 来源:发表于2017-12-15 19:02 被阅读0次
  1. 使用 JDK 的 NIO 实现异步的服务端,大体包括 创建 Channel=>绑定端口=>注册监听=>处理连接建立事件=>注册读写=>处理读写

    public class MyPlainNioServer {
        public void serve(int port) throws IOException {
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            ServerSocket ssocket = serverChannel.socket();
            InetSocketAddress address = new InetSocketAddress(port);
            ssocket.bind(address);
            Selector selector = Selector.open();
            // 将 Channel 注册到 Selector
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
            final ByteBuffer msg = ByteBuffer.wrap("Hi!".getBytes());
            for(;;) {
                try {
                    // 等待需要处理的新事件;阻塞将一直持续到下一个传入事件
                    selector.select();
                } catch (IOException ex) {
                    ex.printStackTrace();
                    break;
                }
                // 获取所有接收事件的 SelectionKey 实例
                Set<SelectionKey> readyKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = readyKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    try {
                        // 检查事件是否是一个新的已经就绪可以被接受的连接
                        if(key.isAcceptable()) {
                            ServerSocketChannel server = (ServerSocketChannel)key.channel();
                            SocketChannel client = server.accept();
                            client.configureBlocking(false);
                            // 接受客户端,并将它注册到选择器
                            client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate());
                            System.out.println("Accepted connection from " + client);
                        }
                        // 检查套接字是否已经准备好写数据
                        if(key.isWritable()) {
                            SocketChannel client = (SocketChannel)key.channel();
                            ByteBuffer buffer = (ByteBuffer)key.attachment();
                            // 将数据写到已连接的客户端
                            while(buffer.hasRemaining()) {
                                if(client.write(buffer) == 0) {
                                    break;
                                }
                            }
                            // 关闭连接
                            client.close();
                        }
                    } catch (IOException ex) {
                        key.cancel();
                        try {
                            key.channel().close();
                        } catch (IOException cex) {
                            // ignore on close
                        }
                    }
                }
            }
        }
    }
    
  2. Netty 版本的 OIO 和 NIO 在实现上的差异仅仅是EventLoopGroupChannel类型的差异上,使用方式完全一致

  3. Channel 接口是传输API的核心,类层次结构如下,每个Channel都持有一个ChannelPipelineChannelConfigChannelConfig中包含了该 Channel 的所有配置设置,并支持热更新

    image.png
  4. ChannelPipeline持有所有将应用于入站和出站数据以及事件的ChannelHandler实例,ChannelHandler的典型用途:

    • 将数据从一种格式转换为另一种格式
    • 提供异常的通知
    • 提供Channel变为活动的或者非活动的通知;
    • 提供当Channel注册到EventLoop或者从EventLoop注销时的通知;
    • 提供有关用户自定义事件的通知
  5. Netty 内置了可以开箱即用的传输

    名称 描述
    NIO io.netty.channel.socket.nio 使用 java.nio.channels 包作为基础——基于选择器的方式
    Epoll io.netty.channel.epoll 由 JNI 驱动的 epoll() 和非阻塞 IO
    OIO io.netty.channel.socket.oio 使用 java.net 包作为基础——使用阻塞流
    Local io.netty.channel.local 可以在 VM 内部通过管道进行通信的本地传输
    Embedded io.netty.channel.embedded Embedded 传输,允许使用 ChannelHandler 而又不需要一个真正的基于网络的传输
image.png

相关文章

网友评论

      本文标题:第 4 章 传输

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