深入学习Netty(4)——Netty编程入门
前言
从学习过BIO、NIO、AIO编程之后,就能很清楚Netty编程的优势,为什么选择Netty,而不是传统的NIO编程。本片博文是Netty的一个入门级别的教程,同时结合时序图与源码分析,以便对Netty编程有更深的理解。
在此博文前,可以先学习了解前几篇博文:
- 深入学习Netty(1)——传统BIO编程
- 深入学习Netty(2)——传统NIO编程
- 深入学习Netty(3)——传统AIO编程
参考资料《Netty In Action》、《Netty权威指南》(有需要的小伙伴可以评论或者私信我)
博文中所有的代码都已上传到Github,欢迎Star、Fork
一、服务端创建
Netty屏蔽了NIO通信的底层细节,减少了开发成本,降低了难度。ServerBootstrap可以方便地创建Netty的服务端
1.服务端代码示例
public void bind (int port) throws Exception { // NIO 线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { // Java序列化编解码 ObjectDecoder ObjectEncoder // ObjectDecoder对POJO对象解码,有多个构造函数,支持不同的ClassResolver,所以使用weakCachingConcurrentResolver // 创建线程安全的WeakReferenceMap对类加载器进行缓存SubReqServer @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 半包处理 ProtobufVarint32FrameDecoder socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder()); // 添加ProtobufDecoder解码器,需要解码的目标类是SubscribeReq socketChannel.pipeline().addLast( new ProtobufDecoder(SubscribeReqProto.SubscribeReq.getDefaultInstance())); socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender()); socketChannel.pipeline().addLast(new ProtobufEncoder()); socketChannel.pipeline().addLast(new SubReqServerHandler()); } }); // 绑定端口,同步等待成功 ChannelFuture f = bootstrap.bind(port).sync(); // 等待所有服务端监听端口关闭 f.channel().closeFuture().sync(); } finally { // 优雅退出,释放线程池资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }