【发布时间】:2019-07-17 19:32:06
【问题描述】:
我使用的是 Netty 3.2.7。我正在尝试在我的客户端中编写功能,以便如果在一定时间(例如 30 秒)后没有写入任何消息,则会向服务器发送一条“保持活动状态”消息。
经过一番挖掘,我发现 WriteTimeoutHandler 应该使我能够做到这一点。我在这里找到了这个解释:https://issues.jboss.org/browse/NETTY-79。
Netty 文档中给出的例子是:
public ChannelPipeline getPipeline() {
// An example configuration that implements 30-second write timeout:
return Channels.pipeline(
new WriteTimeoutHandler(timer, 30), // timer must be shared.
new MyHandler());
}
在我的测试客户端中,我就是这样做的。在 MyHandler 中,我还重写了 exceptionCaught() 方法:
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
if (e.getCause() instanceof WriteTimeoutException) {
log.info("Client sending keep alive!");
ChannelBuffer keepAlive = ChannelBuffers.buffer(KEEP_ALIVE_MSG_STR.length());
keepAlive.writeBytes(KEEP_ALIVE_MSG_STR.getBytes());
Channels.write(ctx, Channels.future(e.getChannel()), keepAlive);
}
}
无论客户端在多长时间内不向通道写入任何内容,我覆盖的 exceptionCaught() 方法都不会被调用。
看WriteTimeoutHandler的源码,它的writeRequested()实现是:
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
long timeoutMillis = getTimeoutMillis(e);
if (timeoutMillis > 0) {
// Set timeout only when getTimeoutMillis() returns a positive value.
ChannelFuture future = e.getFuture();
final Timeout timeout = timer.newTimeout(
new WriteTimeoutTask(ctx, future),
timeoutMillis, TimeUnit.MILLISECONDS);
future.addListener(new TimeoutCanceller(timeout));
}
super.writeRequested(ctx, e);
}
这里,似乎这个实现说,“当请求写入时,进行新的超时。当写入成功时,取消超时。”
使用调试器,看起来确实是这样。写入完成后,超时将被取消。这不是我想要的行为。我想要的行为是:“如果客户端在 30 秒内没有向通道写入任何信息,则抛出 WriteTimeoutException。”
那么,这不是 WriteTimeoutHandler 的用途吗?这就是我从网上阅读的内容中解释它的方式,但实现似乎并没有以这种方式工作。我用错了吗?我应该使用其他东西吗?在我试图重写的同一个客户端的 Mina 版本中,我看到 sessionIdle() 方法被重写以实现我想要的行为,但是这个方法在 Netty 中不可用。
【问题讨论】: