4 传输

 

 

 

OIO和NIO写法大相径庭,但netty的阻塞和非阻塞的代码基本一致,

 

public class NettyOioServer {
  public void server(int port)
      throws Exception {
    final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
    EventLoopGroup group = new OioEventLoopGroup();
    try {
      //创建 ServerBootstrap
      ServerBootstrap b = new ServerBootstrap();
      b.group(group)
          //使用 OioEventLoopGroup以允许阻塞模式(旧的I/O)
          .channel(OioServerSocketChannel.class)
          .localAddress(new InetSocketAddress(port))
          //指定 ChannelInitializer,对于每个已接受的连接都调用它
          .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch)
                throws Exception {
              ch.pipeline().addLast(
                  //添加一个 ChannelInboundHandlerAdapter以拦截和处理事件
                  new ChannelInboundHandlerAdapter() {
                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                      ctx.writeAndFlush(buf.duplicate())
                          //将消息写到客户端,并添加 ChannelFutureListener,
                          //以便消息一被写完就关闭连接
                          .addListener(ChannelFutureListener.CLOSE);
                    }
                  });
            }
          });
      //绑定服务器以接受连接
      ChannelFuture f = b.bind().sync();
      f.channel().closeFuture().sync();
    } finally {
      //释放所有的资源
      group.shutdownGracefully().sync();
    }
  }

 

 

public class NettyNioServer {
  public void server(int port) throws Exception {
    final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
    //为非阻塞模式使用NioEventLoopGroup
    NioEventLoopGroup group = new NioEventLoopGroup();
    try {
      //创建ServerBootstrap
      ServerBootstrap b = new ServerBootstrap();
      b.group(group).channel(NioServerSocketChannel.class)
          .localAddress(new InetSocketAddress(port))
          //指定 ChannelInitializer,对于每个已接受的连接都调用它
          .childHandler(new ChannelInitializer<SocketChannel>() {
                          @Override
                          public void initChannel(SocketChannel ch)
                              throws Exception {
                            ch.pipeline().addLast(
                                //添加 ChannelInboundHandlerAdapter以接收和处理事件
                                new ChannelInboundHandlerAdapter() {
                                  @Override
                                  public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    //将消息写到客户端,并添加ChannelFutureListener,
                                    //以便消息一被写完就关闭连接
                                    ctx.writeAndFlush(buf.duplicate())
                                        .addListener(ChannelFutureListener.CLOSE);
                                  }
                                });
                          }
                        }
          );
      //绑定服务器以接受连接
      ChannelFuture f = b.bind().sync();
      f.channel().closeFuture().sync();
    } finally {
      //释放所有的资源
      group.shutdownGracefully().sync();
    }
  }
}

 

 

 

 

每个Channel 都将会被分配一个ChannelPipeline 和ChannelConfig

ChannelConfig 包含了该Channel 的所有配置设置,并且支持热更新。由于特定的传输可能

具有独特的设置,所以它可能会实现一个ChannelConfig 的子类型。

ChannelHandler 的典型用途包括:

将数据从一种格式转换为另一种格式;

提供异常的通知;

提供Channel 变为活动的或者非活动的通知;

提供当Channel 注册到EventLoop 或者从EventLoop 注销时的通知;

提供有关用户自定义事件的通知。

 

 

 

 

 

 

 

 

 

 

 

零拷贝
零拷贝(zero-copy)是一种目前只有在使用NIO 和Epoll 传输时才可使用的特性。它使你可以快速
高效地将数据从文件系统移动到网络接口,而不需要将其从内核空间复制到用户空间,其在像FTP 或者
HTTP 这样的协议中可以显著地提升性能。但是,并不是所有的操作系统都支持这一特性。特别地,它对
于实现了数据加密或者压缩的文件系统是不可用的——只能传输文件的原始内容。反过来说,传输已被
加密的文件则不是问题。

 

4.3.2 Epoll—用于Linux 的本地非阻塞传输
正如我们之前所说的,Netty 的NIO 传输基于Java 提供的异步/非阻塞网络编程的通用抽象。
虽然这保证了Netty 的非阻塞API 可以在任何平台上使用,但它也包含了相应的限制,因为JDK
为了在所有系统上提供相同的功能,必须做出妥协。
Linux作为高性能网络编程的平台,其重要性与日俱增,这催生了大量先进特性的开发,其
中包括epoll——一个高度可扩展的I/O事件通知特性。这个API自Linux内核版本2.5.442002)被
引入,提供了比旧的POSIX select和poll系统调用①
① 参见Linux 手册页中的epoll(4):http://linux.die.net/man/4/epoll。
更好的性能,同时现在也是Linux上非阻
塞网络编程的事实标准。Linux JDK NIO API使用了这些epoll调用。
Netty为Linux提供了一组NIO API,其以一种和它本身的设计更加一致的方式使用epoll,并
且以一种更加轻量的方式使用中断。①
如果你的应用程序旨在运行于Linux系统,那么请考虑利用
这个版本的传输;你将发现在高负载下它的性能要优于JDK的NIO实现。
这个传输的语义与在图4-2 所示的完全相同,而且它的用法也是简单直接的。相关示例参照
代码清单4-4如果要在那个代码清单中使用epoll 替代NIO,只需要将NioEventLoopGroup
替换为EpollEventLoopGroup , 并且将NioServerSocketChannel.class 替换为
EpollServerSocketChannel.class 即可。

 

Netty的OIO实现

 

 

 

 

 

 

 

 

posted @ 2020-06-07 01:31  lakeslove  阅读(194)  评论(0编辑  收藏  举报