2017-09-08 3 views
0

J'ai la définition suivante pour un serveur basé sur la documentation Netty example:Netty ChannelGroupFutureListener operationComplete jamais appelé

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); 
} 

Je veux écrire quelque message à tous les clients comme celui-ci (méthode de la même classe de serveur):

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"); 
     } 

    }); 
} 

La mise en œuvre est 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"); 

} 

}

Le message a été reçu avec succès par les clients, mais pourquoi la méthode operationComplete du ChannelGroupFutureListener n'a jamais été appelée? J'utilise Netty version 4.0.40.

Répondre

2

Lors de l'extension d'un ChannelOutboundHandlerAdapter, il est important de s'assurer que toutes les interactions natives avec le canal sont correctement propagées. Cela devrait être fait en respectant les ChannelFuture s et les ChannelPromise s.

À l'heure actuelle, vous ignorez le ChannelPromise en amont, ce qui empêche la transmission de notifications de réussite en amont, d'où l'échec de votre avenir. Vous devez utiliser soit l'implémentation de la superclasse, soit la méthode ctx.write(Object, ChannelPromise) pour transmettre correctement votre message à l'amont, et en cas d'erreur, vous devez marquer manuellement l'avenir comme ayant échoué ou réussi, en fonction de vos intentions. .

@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()); 
} 
+0

C'était exactement ce qui manquait! Merci! –