把书读薄(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();
}
}
}
- 初始化EventLoopGroup
- 配置引导类ServerBootstrap作为工具来引导channel建立
- 初始化用于处理连接请求的group(即acceptor)和处理事件的childGroup(即client)
Hello word版代码中用的是同一个NioEventLoop,实际中一般各自分配
- 配置要建立channel的类型
- 置服务端监听的端口
- 配置服务自己的消息处理器,通过childHandler持有
- 创建并初始化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