Netty ChannelGroupFutureListener operationComplete从未调用过

时间:2017-09-08 16:06:56

标签: netty

我对基于Netty文档example的服务器有以下定义:

public void start() throws Exception {

    incommingGroup = new NioEventLoopGroup();
    workerGroup = new NioEventLoopGroup();

    final ServerBootstrap serverBootstrap = new ServerBootstrap();

    serverBootstrap.group(incommingGroup, workerGroup).channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(final Channel channel) throws Exception {
                    final ChannelPipeline pipeline = channel.pipeline();

                    pipeline.addLast("logger", new LoggingHandler());

                    pipeline.addLast("frameDecoder",
                            new DelimiterBasedFrameDecoder(1024, Unpooled.wrappedBuffer(new byte[] { '\r', '\n' }),
                                    Unpooled.wrappedBuffer(new byte[] { '\n' }),
                                    Unpooled.wrappedBuffer(new byte[] { ';' })));

                    pipeline.addLast("stringDecoder", new StringDecoder());
                    pipeline.addLast("stringEncoder", new StringEncoder());

                    pipeline.addLast(new TrackerChannelOutboundHandler());

                    pipeline.addLast(new TrackerChannelInboundHandler(/* eventAdmin */notificationService));

                    channelGroup.add(channel);
                }
            }).option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
            .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

    final ChannelFuture cf = serverBootstrap.bind(notificationService.port());

    final Channel channel = cf.channel();

    channelGroup = new DefaultChannelGroup("group-gpstracker", GlobalEventExecutor.INSTANCE);
    channelGroup.add(channel);
}

我想向所有客户端写一些消息(同一服务器类的方法):

public void write(TrackerMessage trackerMessage) {

    ChannelGroupFuture result = channelGroup.writeAndFlush(trackerMessage, ChannelMatchers.isNonServerChannel());

    result.addListener(new ChannelGroupFutureListener() {

        @Override
        public void operationComplete(ChannelGroupFuture arg0) throws Exception {
            LOGGER.info("Some info");
        }

    });
}

TrackerChannelOutboundHandler实施是:

public class TrackerChannelOutboundHandler extends ChannelOutboundHandlerAdapter {

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {

    if (ctx != null && ctx.channel() != null && ctx.channel().isWritable()) 
        ctx.writeAndFlush(trackerMessage.getMessage() + "\n");

}

}

客户端成功收到消息,但为什么operationComplete的{​​{1}}方法从未被调用?

我使用的是Netty版本:4.0.40。

1 个答案:

答案 0 :(得分:2)

扩展ChannelOutboundHandlerAdapter时,务必确保与频道的所有原生互动都得到适当传播。这应该通过尊重ChannelFutureChannelPromise s。

来完成

目前,您忽略了上游ChannelPromise,阻止了上传成功通知的发送,因此您的未来永远不会被标记为成功。

您应该使用超类实现或ctx.write(Object, ChannelPromise)方法将消息正确传递到上游,如果出现错误,您应该手动将未来标记为失败或成功,具体取决于关于你的意图。

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
    if (ctx != null && ctx.channel() != null && ctx.channel().isWritable()) 
        super.write(ctx, trackerMessage.getMessage() + "\n", promise);
    else
        promise.setFailure(new java.util.concurrent.CancellationException());
}