在几乎所有Netty教程中都会出现的Netty程序, Echo程序
简单来说就是客户端发送任何内容, 服务端都会返回一样的内容

学习最简单的Echo程序, 主要是为了了解Netty使用的模板代码怎么写

1. 客户端实现

客户端的任务就是, 把消息发送给服务端, 并打印服务端返回的信息
客户端需要做下面几件事

  • 建立连接
  • 发送数据
  • 接收数据
  • 打印数据

https://gitee.com/spitman/learnnetty/blob/master/src/main/java/org/zyj/io/example/echo/EchoClient.java

1.1 实现一个发送消息的Handler

  • 当连接建立之后, 立刻发送一条数据

    1. class EchoClientHandler extends ChannelInboundHandlerAdapter {
    2. @Override
    3. public void channelActive(ChannelHandlerContext ctx) {
    4. //建立连接之后, 立刻发送一条消息
    5. String sendMsg = "这是一条消息!";
    6. System.out.println(sendMsg);
    7. ByteBuf byteBuf = Unpooled.copiedBuffer(sendMsg, StandardCharsets.UTF_8);
    8. ctx.writeAndFlush(byteBuf);
    9. }
    10. @Override
    11. public void channelRead(ChannelHandlerContext ctx, Object msg) {
    12. //读取服务端返回的信息
    13. ByteBuf buf = (ByteBuf) msg;
    14. if (buf.isReadable()){
    15. System.out.println(buf.toString(StandardCharsets.UTF_8));
    16. }
    17. }
    18. }

    1.2 客户端启动Netty

    1. public static void main(String[] args) throws InterruptedException {
    2. EventLoopGroup group = new NioEventLoopGroup();
    3. try {
    4. Bootstrap b = new Bootstrap();
    5. b.group(group)
    6. .channel(NioSocketChannel.class)
    7. .option(ChannelOption.TCP_NODELAY, true)
    8. .handler(new ChannelInitializer<SocketChannel>() {
    9. @Override
    10. protected void initChannel(SocketChannel ch) {
    11. ch.pipeline().addLast(new EchoClientHandler());
    12. }
    13. });
    14. ChannelFuture f = b.connect("127.0.0.1", 11223).sync();
    15. f.channel().closeFuture().sync();//阻塞主线程, 程序不会退出
    16. } finally {
    17. group.shutdownGracefully();
    18. }
    19. }
  • channel(NioSocketChannel.class) : 这里指定使用NioChannel的方式建立连接(依赖JDK实现), 不同的SocketChannel实现类是不同的操作系统接口, 会提供不同的特性, 可使用的option参数也有所区别

  • option(ChannelOption._TCP_NODELAY_, true) : 不需要等待组装成大TCP包, 这样延迟会比较低
  • ch.pipeline().addLast(new EchoClientHandler()) : 添加ChannelHandler

    服务端实现

    回音服务, 就是将客户端发送的信息, 原样返回
    要实现这个功能, 服务端要做下面几件事

  • 建立连接

  • 读取数据
  • 发送数据

https://gitee.com/spitman/learnnetty/blob/master/src/main/java/org/zyj/io/example/echo/EchoServer.java

2.1 服务端回音Handler

  1. class EchoServerHandler extends ChannelInboundHandlerAdapter {
  2. @Override
  3. public void channelRead(ChannelHandlerContext ctx, Object msg) {
  4. ByteBuf receivedMsg = (ByteBuf) msg;
  5. System.out.println(receivedMsg.toString(StandardCharsets.UTF_8));//打印一下第一个传进来的msg是什么
  6. //ChannelHandlerContext对象提供了多种操作, 是你可以出发各种IO事件和IO操作
  7. //ctx.write(msg); //直接将msg写入channel中, 不需要显示的释放ByteBuf, Netty会帮我们释放
  8. //一个TCP消息包, 只发送一点点数据, 就很浪费网络, 包头是固定长度
  9. //所以ctx.write(msg) 这一步仅仅只是写入缓存中, 并没有真正发送出去
  10. //想要立刻发送出去, 需要显示的调用ctx.flush()
  11. //ctx.flush();//将缓存中的数据发送出去
  12. //或者可以简单的使用一行代码来简洁的表示
  13. ctx.writeAndFlush(msg);
  14. }
  15. }

2.2 服务端启动Netty

  1. public static void main(String[] args) throws Throwable {
  2. EventLoopGroup bossGroup = new NioEventLoopGroup();
  3. EventLoopGroup workerGroup = new NioEventLoopGroup();
  4. try {
  5. ServerBootstrap b = new ServerBootstrap();
  6. b.group(bossGroup, workerGroup)
  7. .channel(NioServerSocketChannel.class)
  8. .childHandler(new ChannelInitializer<NioSocketChannel>() {
  9. @Override
  10. public void initChannel(NioSocketChannel ch) {//每次建立连接的时候都会被调用
  11. ch.pipeline().addLast(new EchoServerHandler());
  12. }
  13. })
  14. .option(ChannelOption.SO_BACKLOG, 128)
  15. .childOption(ChannelOption.SO_KEEPALIVE, true);
  16. ChannelFuture f = b.bind(11223).sync();
  17. f.channel().closeFuture().sync();
  18. } finally {
  19. workerGroup.shutdownGracefully();
  20. bossGroup.shutdownGracefully();
  21. }
  22. }
  • option(ChannelOption._SO_BACKLOG_, 128) : 套接字listen函数中的backlog参数, 等待处理连接的队列大小; 如果backlog过小,就可能出现Accept的速度跟不上,A,B队列满了,就会导致客户端无法建立连接
  • childOption(ChannelOption._SO_KEEPALIVE_, true) : 当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,超过了2个小时,本地的TCP实现会发送一个数据包给远程的 socket,如果远程没有发回响应,TCP会持续尝试11分钟,直到响应为止,如果在12分钟的时候还没响应,TCP尝试关闭socket连接。
  • ch.pipeline().addLast(new EchoServerHandler()) : 添加回音Handler

    3. 运行效果

    四.Netty实现回音程序 - 图1
    四.Netty实现回音程序 - 图2