netty

认识netty

什么是netty

  • netty是一个利用java的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的API的客服端/服务器框架。

netty与Tomact有什么区别

  • netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,它的实质是一个基于http协议的web容器,但事netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和Tomcat最大的不同

netty为什么受欢迎

  • netty是一款受到大公司青睐的框架,netty能够受到青睐的原因有三:

    1. 并发高

      netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比BIO(Blocking I/O,阻塞IO),它的并发性能得到了很大提高。一下两张图是BIO和NIO

      img

      ​ 阻塞io通信方式

      img

      ​ 非阻塞io

    2. 传输快

      netty的传输快其实也是依赖NIO的另一个特性–零拷贝。在java中,内存分为堆内存、栈内存和字符串常量池,其中堆内存是占用内空间最大的一块,也是java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过socket缓冲区,也就是说一个数据会被朝北两次才能到达它的终点,如果数据量大,就会造成不必要的浪费。netty针对这种情况,使用了零拷贝,当它需要接收数据的时候,它会在堆内存中开辟一块内存,数据就直接从IO读到了那块内存中,在netty里面通过ByteBuf可以直接对这些数据进行操作,从而加快了传输速度。

    3. 封装好

      直接上代码。

      BIO:

      public class PlainNioServer {
          public void serve(int port) throws IOException {
              ServerSocketChannel serverChannel = ServerSocketChannel.open();
              serverChannel.configureBlocking(false);
              ServerSocket ss = serverChannel.socket();
              InetSocketAddress address = new InetSocketAddress(port);
              ss.bind(address);                                            //1
              Selector selector = Selector.open();                        //2
              serverChannel.register(selector, SelectionKey.OP_ACCEPT);    //3
              final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
              for (;;) {
                  try {
                      selector.select();                                    //4
                  } catch (IOException ex) {
                      ex.printStackTrace();
                      // handle exception
                      break;
                  }
                  Set<SelectionKey> readyKeys = selector.selectedKeys();    //5
                  Iterator<SelectionKey> iterator = readyKeys.iterator();
                  while (iterator.hasNext()) {
                      SelectionKey key = iterator.next();
                      iterator.remove();
                      try {
                          if (key.isAcceptable()) {                //6
                              ServerSocketChannel server =
                                      (ServerSocketChannel)key.channel();
                              SocketChannel client = server.accept();
                              client.configureBlocking(false);
                              client.register(selector, SelectionKey.OP_WRITE |
                                      SelectionKey.OP_READ, msg.duplicate());    //7
                              System.out.println(
                                      "Accepted connection from " + client);
                          }
                          if (key.isWritable()) {                //8
                              SocketChannel client =
                                      (SocketChannel)key.channel();
                              ByteBuffer buffer =
                                      (ByteBuffer)key.attachment();
                              while (buffer.hasRemaining()) {
                                  if (client.write(buffer) == 0) {        //9
                                      break;
                                  }
                              }
                              client.close();                    //10
                          }
                      } catch (IOException ex) {
                          key.cancel();
                          try {
                              key.channel().close();
                          } catch (IOException cex) {
                              // 在关闭时忽略
                          }
                      }
                  }
              }
          }
      }
      

      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 b = new ServerBootstrap();        //1
      
                  b.group(group)                                    //2
                   .channel(OioServerSocketChannel.class)
                   .localAddress(new InetSocketAddress(port))
                   .childHandler(new ChannelInitializer<SocketChannel>() {//3
                       @Override
                       public void initChannel(SocketChannel ch) 
                           throws Exception {
                           ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {            //4
                               @Override
                               public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                   ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);//5
                               }
                           });
                       }
                   });
                  ChannelFuture f = b.bind().sync();  //6
                  f.channel().closeFuture().sync();
              } finally {
                  group.shutdownGracefully().sync();        //7
              }
          }
      }
      

      从代码上看,netty就已经秒杀传统socket编程了,下面介绍一下netty中重要的概念。

netty重要概念

  • Channel

    数据传输刘,与channel相关的概念有一下四个,如图:

    img

    • Channel:表示一个连接,可以理解为一个请求,就是一个Channel。
    • ChannelHandler:核心处理业务就在之类,用于处理业务请求。
    • ChannelHandlerContext:用于传输业务数据。
    • ChannelPipline:用于保存处理过程需要用到的ChannelHandler和ChannelHandlerContext。
  • ByteBuf

    ByteBuf是一个存储字节的容器,最大的特点就是使用方便,它既有自己的读索引和写索引,方便对争端字节缓存进行读写,也支持get/set,方便对其中每一个字节进行读写,它的数据结构入下:

    img

  • Codec

    netty中的编码/解码器,通过它能完成字节与pojo、pojo与byte的相互转换,从而达到自定义协议的目的。

读写,也支持get/set,方便对其中每一个字节进行读写,它的数据结构入下:

[外链图片转存中…(img-fwAH71LD-1644737484407)]

  • Codec

    netty中的编码/解码器,通过它能完成字节与pojo、pojo与byte的相互转换,从而达到自定义协议的目的。

    在netty里面最有名的就是HttpRequestDecoder和HttpResponseEncoder了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值