专栏名称: 爬蜥
目录
相关文章推荐
51好读  ›  专栏  ›  爬蜥

从Netty版hello world看Netty源码,我们能看到什么?

爬蜥  · 掘金  ·  · 2018-07-04 02:18

正文

阅读 19

从Netty版hello world看Netty源码,我们能看到什么?

把书读薄(Netty in Action第二章) + Netty启动源码

Netty服务端代码的hello world怎么写?

public class EchoServer {
    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }
    public static void main(String[]args)throws Exception{
        new EchoServer(8888).start();
    }
    public void start() throws Exception{
        final EchoServerHandler handler = new EchoServerHandler();
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            ServerBootstrap b = new ServerBootstrap();
            b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(handler);
                        }
                    });
            ChannelFuture f = b.bind().sync();
            f.channel().closeFuture().sync();
        }finally {
            group.shutdownGracefully().sync();
        }
    }
}
  1. 初始化EventLoopGroup

所谓的EventLoopGroup,组(group)的概念表现在它自身维护了一个数组children,默认维护逻辑处理核数2倍的NioEventLoop线程,并通过chooser来方便的获取下一个要执行的线程。实际处理的是NioEventLoop,它的部分类结构如下:

实质上的线程执行,就是启动一个java Thread,然后从taskQuene中获取要执行的任务,在run方法中执行。

  1. 配置引导类ServerBootstrap作为工具来引导channel建立

  • 初始化用于处理连接请求的group(即acceptor)和处理事件的childGroup(即client)

Hello word版代码中用的是同一个NioEventLoop,实际中一般各自分配

  • 配置要建立channel的类型
  • 置服务端监听的端口
  • 配置服务自己的消息处理器,通过childHandler持有
  1. 创建并初始化channel

在管道的最后添加ChannelInitializer的方式则会在管道注册完成之后,往管道中 添加一个ServerBootstrapAcceptor(它是InboundHandler),它持有对childGroup(client)和childHandler的引用,而ChannelInitializer这个InboundHandler在完成它的使命之后,就会从管道中被移除, 至此完成channel的初始化。

ServerBootstrapAcceptor 最开始在客户端建立连接的时候执行调用(后续读消息调用),入口是 doReadMessages,读到消息之后,从Head沿着InBoundHandler到ServerBootstrapAcceptor,触发读事件,此时执行注册childGroup到这个channel,也就是每次都用childGroup来处理读到的消息

 public final void channelRegistered(ChannelHandlerContext ctx) throws Exception {
 //管道注册完成之后触发
        ChannelPipeline pipeline = ctx.pipeline(); 
        boolean success = false






请到「今天看啥」查看全文