[英]Always failed to close channel (netty) from server-side when the client has been physically killed
It's a web-socket application based on netty.它是一个基于 netty 的 web-socket 应用程序。 However, when the client is physically killed without sending a
CloseWebSocketFrame
, server needs to know the channel has been closed and do some cleaning work.然而,当客户端在没有发送
CloseWebSocketFrame
情况下被物理杀死时,服务器需要知道通道已经关闭并做一些清理工作。 IdleStateHandler
is used to monitor whether the channel is idle. IdleStateHandler
用于监控通道是否空闲。
Here is the channel handler pipeline.这是通道处理程序管道。
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
SSLEngine sslEngine = new SSLServiceBase().getSSLContext().createSSLEngine();
sslEngine.setUseClientMode(false);
sslEngine.setNeedClientAuth(true);
... // business process
pipeline.addLast(new IdleStateHandler(30, 10, 0, TimeUnit.SECONDS));
pipeline.addLast(new HeartbeatHandler());
}
This is the userEventTriggered
method of HeartbeatHandler
which is used to do some cleaning work when channel is closed from the client abnormally.这是
HeartbeatHandler
的userEventTriggered
方法,用于在客户端异常关闭通道时做一些清理工作。
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (IdleState.WRITER_IDLE.equals(event.state())) {
ctx.writeAndFlush(new PingWebSocketFrame()).addListener(future -> {
if (!future.isSuccess()) {
ChannelFuture closeFuture = ctx.channel().close();
if (closeFuture.isSuccess()) {
System.out.println("ping faild, channel close successfully");
} else {
System.out.println("ping failed, channel close failed");
}
} else {
System.out.println("Ping succeed, keep the channel.");
}
});
}
} else {
super.userEventTriggered(ctx, evt);
}
}
Actually, I'm continuously getting 'close failed'
, and the channel is still alive from the server view.实际上,我不断收到
'close failed'
,并且从服务器的角度来看,该频道仍然存在。 Could anyone let me know why the channel can't be closed or how to close?谁能告诉我为什么无法关闭频道或如何关闭? Thanks a lot.
非常感谢。
I suspect the close was not done yet (remember it is an async operation).我怀疑关闭还没有完成(记住这是一个异步操作)。 Change the code to:
将代码更改为:
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (IdleState.WRITER_IDLE.equals(event.state())) {
ctx.writeAndFlush(new PingWebSocketFrame()).addListener(future -> {
if (!future.isSuccess()) {
ctx.close().addListener(closeFuture -> {
If (closeFuture.isSuccess()) {
System.out.println("ping faild, channel close successfully");
} else {
System.out.println("ping failed, channel close failed");
// TODO: You may also want to log the reason why the close operation failed.
// closeFuture.cause() will contain why.
}
});
} else {
System.out.println("Ping succeed, keep the channel.");
}
});
}
} else {
super.userEventTriggered(ctx, evt);
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.