likes
comments
collection
share

Netty尝鲜

作者站长头像
站长
· 阅读数 12

何谓Netty

  • Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
  • Netty: Home,不要怕英文。

异步、事件驱动。

第一个程序

环境依赖

<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-all</artifactId>
  <version>4.1.78.Final</version>
</dependency>

写一个经典的Hello World程序

  • 先不管用到的类有啥功能。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

public class HttpServer {
    public static void main( String[] args ) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new MyServerInitializer());
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception exception){
            exception.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("httpServerCodec", new HttpServerCodec())
                .addLast("testHttpServerHandler", new MyHttpServerHandler())
                .addLast("myException",new ExceptionHandler());
    }
}
class MyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
            ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8);
            FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK, content);
            fullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            fullHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
            ctx.writeAndFlush(fullHttpResponse);
    }
}
class ExceptionHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.err.println(this.getClass().getName() + " 异常处理,e:" + cause);
    }
}

Netty尝鲜

用到的Netty组件

大致名称及功能

  • Netty的核心组件包括:
    1. Channel:代表一个网络连接,可以读取和写入数据。
    2. EventLoop:处理Channel上的所有事件,包括连接的建立和关闭、读取和写入数据等。
    3. ChannelHandler:处理所有的I/O事件,例如数据的读取和写入、连接的建立和关闭等。
    4. ChannelPipeline:是一组有序的ChannelHandler,用于处理Channel的I/O事件。数据在进入和离开Channel时,会经过一系列的ChannelHandler进行处理。
  • Netty的架构采用了Reactor模式。当一个Channel有I/O事件发生时,Netty会通过EventLoop将事件派发给对应的ChannelHandler进行处理。由于Netty采用了异步非阻塞的I/O模型,可以大大提高网络应用程序的性能和可伸缩性。
  • 当使用Netty开发应用程序时,通常需要配置ChannelPipeline,这可以通过使用ChannelInitializer来完成。ChannelInitializer是一种特殊类型的ChannelHandler,它负责初始化ChannelPipeline。在初始化过程中,开发者可以添加自己的ChannelHandler,并设置不同的ChannelHandler的顺序。
  • 另外,ChannelHandler有许多不同的方法可以实现,例如:
    1. channelActive:在连接建立时被调用。
    2. channelRead:当读取到数据时被调用。
    3. channelReadComplete:当读取到的数据已经被处理完毕时被调用。
    4. channelInactive:在连接关闭时被调用。
    5. exceptionCaught:在发生异常时被调用。

启动的特定模式

  • 首先,通过创建两个EventLoopGroup来分别处理连接的请求和网络I/O事件。其中,bossGroup用于接收连接请求,workerGroup用于处理I/O事件
  • 然后,通过创建一个ServerBootstrap对象来启动服务器,其中:
    • group方法将bossGroup和workerGroup设置为服务器的两个EventLoopGroup。
    • channel方法设置了服务器使用的通道类型,这里使用了NioServerSocketChannel。
    • handler方法添加的处理器是针对bossGroup
    • childHandler方法设置了用于处理Channel的初始化器,就是针对workerGroup
  • 最后,通过调用bind方法来绑定服务器的端口号,并调用sync方法来阻塞等待服务器启动完成。在启动完成后,使用closeFuture方法来等待服务器的关闭,以确保程序的正常退出。
  • 在程序退出时,通过调用shutdownGracefully方法来优雅地关闭EventLoopGroup,以释放资源和清理内存。