我对基于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。
答案 0 :(得分:2)
扩展ChannelOutboundHandlerAdapter
时,务必确保与频道的所有原生互动都得到适当传播。这应该通过尊重ChannelFuture
和ChannelPromise
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());
}