当前位置:   article > 正文

Netty4自学笔记 (3) - Netty NIO Server和Client 样例说明

Netty4自学笔记 (3) - Netty NIO Server和Client 样例说明

全文详见个人独立博客:Netty4自学笔记 (3) - Netty NIO Server和Client 样例说明

Netty4自学笔记 (3) - Netty NIO Server和Client 样例说明更新节奏缓慢,因为每晚学习注意力不够集中,学习进展缓慢。本还给自己找了一大堆其他理由,但摸着良心问自己,似乎只有这个理由说的通。 想搞懂的太多,却始终没搞明白。先看一个用Netty编写的NIO Server的样例。 package com.coderli.nettylab.guide; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * @author lihongzhe 2018/7/24 23:19 */ public class NettyNioServer { public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(7060).sync(); // (5) f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } ServerHanler代码 package com.coderli.nettylab.guide; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * @author lihongzhe 2018/7/24 23:58 */ public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("Receive Msg."); ((ByteBuf) msg).release(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } 上述代码改自Netty官方手册。NettyNioServer代码中做了几处标记,分别对应我们在Netty4 自学笔记(2)中讨论的关键点,简析如下: 标记1是构建了两个线程池,我们在Java NIO学习中提到的,针对Select的实现方式,如果想要实现并发,只需要在事件处理时,启用多线程处理即可,此处的workerGroup正是为此服务。而在Netty中,不仅仅对于事件到达后的处理启用了线程池,为了实现高并发,Netty开启多个线程注册多个Selector同时处理事件。Netty中,默认线程池数量为,cpu核心数 * 2(NettyRuntime.availableProcessors() * 2),个人认为Selector线程数过多意义也不大,关键还是在于事件分发后的后续处理,即work线程。同样,这里worker线程池的默认数量与boss一致,因此在业务实现中应注意异步处理worker中的回调,以免堵塞worker,影响并发。 标记2的ServerBootstrap是Netty封装的统一配置并启动Server的启动器,在Java NIO学习中提到的Channel(标记3)和事件处理器Handler(标记4),都统一配置在此。标记3处指定不同类型的Channel(例如:Nio、Oio),底层便可方便的在不同的通信模式下进行切换,上层无感知。 标记5,一切配置好后,启动器绑定到指定端口。 从样例代码的直观感觉来说,Netty提供了良好的封装,无论是Server还是事件处理的Handler,Netty几乎帮我们做好了一切。对于开发人员来说,只需要关注于Netty提供的Handler的回调时机,开发自己的业务逻辑,比直接使用Java NIO的API节约了很多的开工作量,而且保证了代码的健壮性和多线程支持。 因此,我下一步的思路就是去研究一下Netty中Handler的回调机制,真正掌握才可开发逻辑正确的代码。 本文的最后,把Client端的代码补充完整,以便调试, NettyNioClient package com.coderli.nettylab.guide; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; /** * @author lihongzhe 2018/8/6 22:55 */ public class NettyNioClient { public static void main(String[] args) throws InterruptedException { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ClientHandler()); } }); ChannelFuture f = b.connect("127.0.0.1", 7060).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } } ClientHandler package com.coderli.nettylab.guide; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.Date; /** * @author lihongzhe 2018/8/6 23:13 */ public class ClientHandler extends ChannelInboundHandlerAdapter { private ByteBuf buf; @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("Channel Registered, Client."); ctx.fireChannelRegistered(); } @Override public void handlerAdded(ChannelHandlerContext ctx) { System.out.println("Handler added."); buf = ctx.alloc().buffer(4); } @Override public void handlerRemoved(ChannelHandlerContext ctx) { buf.release(); buf = null; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf m = (ByteBuf) msg; buf.writeBytes(m); m.release(); if (buf.readableBytes() >= 4) { long currentTimeMillis = (buf.readUnsignedInt() - 2208988800L) * 1000L; System.out.println(new Date(currentTimeMillis)); ctx.close(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } 后续的研究,我也会基于上述代码加以改造和调试。icon-default.png?t=N7T8https://www.coderli.com/netty4-3-netty-server-client-demo/

欢迎加入群聊,一起交流探讨:【Java学习交流(982860385)】 

更新节奏缓慢,因为每晚学习注意力不够集中,学习进展缓慢。本还给自己找了一大堆其他理由,但摸着良心问自己,似乎只有这个理由说的通。

想搞懂的太多,却始终没搞明白。先看一个用Netty编写的NIO Server的样例。

  1. package com.coderli.nettylab.guide;
  2. import io.netty.bootstrap.ServerBootstrap;
  3. import io.netty.channel.ChannelFuture;
  4. import io.netty.channel.ChannelInitializer;
  5. import io.netty.channel.ChannelOption;
  6. import io.netty.channel.EventLoopGroup;
  7. import io.netty.channel.nio.NioEventLoopGroup;
  8. import io.netty.channel.socket.SocketChannel;
  9. import io.netty.channel.socket.nio.NioServerSocketChannel;
  10. /**
  11. * @author lihongzhe 2018/7/24 23:19
  12. * @site https://www.coderli.com
  13. */
  14. public class NettyNioServer {
  15. public static void main(String[] args) throws InterruptedException {
  16. EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
  17. EventLoopGroup workerGroup = new NioEventLoopGroup();
  18. try {
  19. ServerBootstrap b = new ServerBootstrap(); // (2)
  20. b.group(bossGroup, workerGroup)
  21. .channel(NioServerSocketChannel.class) // (3)
  22. .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
  23. @Override
  24. public void initChannel(SocketChannel ch) throws Exception {
  25. ch.pipeline().addLast(new ServerHandler());
  26. }
  27. })
  28. .option(ChannelOption.SO_BACKLOG, 128)
  29. .childOption(ChannelOption.SO_KEEPALIVE, true);
  30. ChannelFuture f = b.bind(7060).sync(); // (5)
  31. f.channel().closeFuture().sync();
  32. } finally {
  33. workerGroup.shutdownGracefully();
  34. bossGroup.shutdownGracefully();
  35. }
  36. }
  37. }

ServerHanler代码

  1. package com.coderli.nettylab.guide;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.channel.ChannelHandlerContext;
  4. import io.netty.channel.ChannelInboundHandlerAdapter;
  5. /**
  6. * @author lihongzhe 2018/7/24 23:58
  7. * @site https://www.coderli.com
  8. */
  9. public class ServerHandler extends ChannelInboundHandlerAdapter {
  10. @Override
  11. public void channelRead(ChannelHandlerContext ctx, Object msg) {
  12. System.out.println("Receive Msg.");
  13. ((ByteBuf) msg).release();
  14. }
  15. @Override
  16. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  17. cause.printStackTrace();
  18. ctx.close();
  19. }
  20. }

上述代码改自Netty官方手册。NettyNioServer代码中做了几处标记,分别对应我们在Netty4 自学笔记(2)中讨论的关键点,简析如下:

 全文详见个人独立博客:

Netty4自学笔记 (3) - Netty NIO Server和Client 样例说明

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/928131
推荐阅读
相关标签
  

闽ICP备14008679号