我有一个问题:Netty没有正确删除在handlerRemoved方法中断开连接的通道。将客户端重新连接到服务器时,出现以下错误:

io.netty.channel.ChannelPipelineException: com.test.netty.NettyServerHandler is not a @Sharable handler, so can't be added or removed multiple times.
            at io.netty.channel.DefaultChannelPipeline.checkMultiplicity(DefaultChannelPipeline.java:464)
            at io.netty.channel.DefaultChannelPipeline.addLast0(DefaultChannelPipeline.java:136)
            at io.netty.channel.DefaultChannelPipeline.addLast(DefaultChannelPipeline.java:129)
            at io.netty.channel.DefaultChannelPipeline.addLast(DefaultChannelPipeline.java:257)
            at io.netty.channel.DefaultChannelPipeline.addLast(DefaultChannelPipeline.java:244)
            at com.test.netty.NettyServer$1.initChannel(NettyServer.java:46)
            at com.test.netty.NettyServer$1.initChannel(NettyServer.java:38)
            at io.netty.channel.ChannelInitializer.channelRegistered(ChannelInitializer.java:69)
            at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRegistered(AbstractChannelHandlerContext.java:133)
            at io.netty.channel.AbstractChannelHandlerContext.fireChannelRegistered(AbstractChannelHandlerContext.java:119)
            at io.netty.channel.DefaultChannelPipeline.fireChannelRegistered(DefaultChannelPipeline.java:733)
            at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:449)
            at io.netty.channel.AbstractChannel$AbstractUnsafe.access$100(AbstractChannel.java:377)
            at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:423)
            at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380)
            at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
            at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
            at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
            at java.lang.Thread.run(Thread.java:818)

该处理程序如下所示:
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
    Channel incoming = ctx.channel();
    channels.remove(ctx.channel());
}

我正在使用group.shutDownGracefully();停止客户端

handlerAdded方法:
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        channels.add(ctx.channel());
}

主服务器:
public final class NettyServer {

    public EventLoopGroup bossGroup;
    public EventLoopGroup workerGroup;
    int PORT = 14930;

    NettyServerHandler clientHandler = new NettyServerHandler();

    public NettyServer(int PORT) {
        this.PORT = PORT;
        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
    }

    public void run() throws Exception {
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                                      @Override
                                      public void initChannel(SocketChannel ch) throws Exception {
                                          ChannelPipeline pipeline = ch.pipeline();

                                          pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
                                          pipeline.addLast(new StringDecoder());
                                          pipeline.addLast(new StringEncoder());
                                          pipeline.addLast(clientHandler);
                                      }
                                  }
                    );

            b.bind(PORT).sync().channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

handlerRemoved方法被执行,我检查了此方法的打印内容。

最佳答案

如果不是@Sharable,则无法再次添加相同的处理程序。您将需要创建一个新实例

09-11 19:32