认识netty
什么是netty
- netty是一个利用java的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的API的客服端/服务器框架。
netty与Tomact有什么区别
- netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,它的实质是一个基于http协议的web容器,但事netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和Tomcat最大的不同
netty为什么受欢迎
netty是一款受到大公司青睐的框架,netty能够受到青睐的原因有三:
并发高
netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比BIO(Blocking I/O,阻塞IO),它的并发性能得到了很大提高。一下两张图是BIO和NIO
阻塞io通信方式
非阻塞io
传输快
netty的传输快其实也是依赖NIO的另一个特性–零拷贝。在java中,内存分为堆内存、栈内存和字符串常量池,其中堆内存是占用内空间最大的一块,也是java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过socket缓冲区,也就是说一个数据会被朝北两次才能到达它的终点,如果数据量大,就会造成不必要的浪费。netty针对这种情况,使用了零拷贝,当它需要接收数据的时候,它会在堆内存中开辟一块内存,数据就直接从IO读到了那块内存中,在netty里面通过ByteBuf可以直接对这些数据进行操作,从而加快了传输速度。
封装好
直接上代码。
BIO:
publicclassPlainNioServer{publicvoidserve(intport)throwsIOException{ServerSocketChannelserverChannel=ServerSocketChannel.open();serverChannel.configureBlocking(false);ServerSocketss=serverChannel.socket();InetSocketAddressaddress=newInetSocketAddress(port);ss.bind(address);//1Selectorselector=Selector.open();//2serverChannel.register(selector,SelectionKey.OP_ACCEPT);//3finalByteBuffermsg=ByteBuffer.wrap("Hi!\r\n".getBytes());for(;;){try{selector.select();//4}catch(IOExceptionex){ex.printStackTrace();// handle exceptionbreak;}Set<SelectionKey>readyKeys=selector.selectedKeys();//5Iterator<SelectionKey>iterator=readyKeys.iterator();while(iterator.hasNext()){SelectionKeykey=iterator.next();iterator.remove();try{if(key.isAcceptable()){//6ServerSocketChannelserver=(ServerSocketChannel)key.channel();SocketChannelclient=server.accept();client.configureBlocking(false);client.register(selector,SelectionKey.OP_WRITE|SelectionKey.OP_READ,msg.duplicate());//7System.out.println("Accepted connection from "+client);}if(key.isWritable()){//8SocketChannelclient=(SocketChannel)key.channel();ByteBufferbuffer=(ByteBuffer)key.attachment();while(buffer.hasRemaining()){if(client.write(buffer)==0){//9break;}}client.close();//10}}catch(IOExceptionex){key.cancel();try{key.channel().close();}catch(IOExceptioncex){// 在关闭时忽略}}}}}}netty:
publicclassNettyOioServer{publicvoidserver(intport)throwsException{finalByteBufbuf=Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n",Charset.forName("UTF-8")));EventLoopGroupgroup=newOioEventLoopGroup();try{ServerBootstrapb=newServerBootstrap();//1b.group(group)//2.channel(OioServerSocketChannel.class).localAddress(newInetSocketAddress(port)).childHandler(newChannelInitializer<SocketChannel>(){//3@OverridepublicvoidinitChannel(SocketChannelch)throwsException{ch.pipeline().addLast(newChannelInboundHandlerAdapter(){//4@OverridepublicvoidchannelActive(ChannelHandlerContextctx)throwsException{ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);//5}});}});ChannelFuturef=b.bind().sync();//6f.channel().closeFuture().sync();}finally{group.shutdownGracefully().sync();//7}}}从代码上看,netty就已经秒杀传统socket编程了,下面介绍一下netty中重要的概念。
netty重要概念
Channel
数据传输流,与channel相关的概念有一下四个,如图:
- Channel:表示一个连接,可以理解为一个请求,就是一个Channel。
- ChannelHandler:核心处理业务就在之类,用于处理业务请求。
- ChannelHandlerContext:用于传输业务数据。
- ChannelPipline:用于保存处理过程需要用到的ChannelHandler和ChannelHandlerContext。
ByteBuf
ByteBuf是一个存储字节的容器,最大的特点就是使用方便,它既有自己的读索引和写索引,方便对争端字节缓存进行读写,也支持get/set,方便对其中每一个字节进行读写,它的数据结构入下:
Codec
netty中的编码/解码器,通过它能完成字节与pojo、pojo与byte的相互转换,从而达到自定义协议的目的。
读写,也支持get/set,方便对其中每一个字节进行读写
Codec
netty中的编码/解码器,通过它能完成字节与pojo、pojo与byte的相互转换,从而达到自定义协议的目的。
在netty里面最有名的就是HttpRequestDecoder和HttpResponseEncoder了。