Я использую Netty 3.2.7. Я пытаюсь написать функциональность в моем клиенте, чтобы, если никакие сообщения не записываются через определенное количество времени (скажем, 30 секунд), сообщение "keep-alive" отправляется на сервер.
После некоторого копания я обнаружил, что 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.