【Java】Netty中closeFuture添加监听事件示例

1. 需求

  • 客户端向服务端发送信息,服务端将信息打印
  • 客户端接收键盘输入到信息循环向服务端发送信息
  • 客户端接收键盘输入‘q’时关闭

2.服务端代码

import io.netty.bootstrap.ServerBootstrap;`在这里插入代码片`
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.Charset;

@Slf4j
public class Server {
    
    
    public static void main(String[] args) {
    
    
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup(2);
        ServerBootstrap serverBootstrap = new ServerBootstrap()
                .group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
    
    
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
    
    
                        ch.pipeline().addLast("handler1", new ChannelInboundHandlerAdapter() {
    
    
                            @Override                                         // ByteBuf
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    
    
                                ByteBuf buf = (ByteBuf) msg;
                                String s = buf.toString(Charset.defaultCharset());
                                log.debug(s);
                            }
                        });

                    }
                });
        ChannelFuture channelFuture = serverBootstrap.bind(8080);
    }
}

客户端代码

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.util.Scanner;

@Slf4j
public class Client {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        NioEventLoopGroup group = new NioEventLoopGroup();
        ChannelFuture channelFuture = new Bootstrap()
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
    
    
                    @Override // 在连接建立后被调用
                    protected void initChannel(NioSocketChannel ch) throws Exception {
    
    
                        ch.pipeline().addLast(new StringEncoder());
                    }
                })
                .connect(new InetSocketAddress("localhost", 8080));
        System.out.println(channelFuture.getClass());
        Channel channel = channelFuture.sync().channel();
        log.debug("{}", channel);
        new Thread(()->{
    
    
            Scanner scanner = new Scanner(System.in);
            while (true) {
    
    
                String line = scanner.nextLine();
                if ("q".equals(line)) {
    
    
                    channel.close(); // close 异步操作 1s 之后
                    break;
                }
                channel.writeAndFlush(line);
            }
        }, "input").start();

        // 获取 CloseFuture 对象, 1) 方法1 同步处理关闭, 2) 方法2 异步处理关闭
        ChannelFuture closeFuture = channel.closeFuture();

        /*
        方法一
        log.debug("waiting close...");
        closeFuture.sync();
        log.debug("处理关闭之后的操作");
        group.shutdownGracefully();
        */

        // 方法二
        closeFuture.addListener(new ChannelFutureListener() {
    
    
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
    
    
                log.debug("处理关闭之后的操作");
                group.shutdownGracefully();// 优雅关闭
            }
        });
        // 方法三:拉姆达表达式简化方法二
        //closeFuture.addListener((ChannelFutureListener) future -> {
    
    
        //    log.debug("处理关闭之后的操作");
        //    group.shutdownGracefully();
        //});

    }
}

重点关注方法二
channel.closeFuture()获取处理closeFuture对象,使用其.addListener()方法添加一个ChannelFutureListener监听器,在关闭操作完成后执行相应的操作,然后调用group.shutdownGracefully()优雅地关闭事件循环组。

运行

依次运行服务端和客户端,客户端输入:
在这里插入图片描述
服务端输出:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/AwesomeP/article/details/131561040