Netty: 使用 `IdleStateHandler` 检测断开连接

3
我阅读了IdleStateHandler的文档,并且按照文档在我的服务器中实现了它,但是我不知道如何准确地判断客户端是否已经断开连接,例如客户端失去了WiFi连接。
据我理解,在我的处理器中,当客户端断开连接时会触发channelInactive()方法,然后使用IdleStateHandler,如果在指定时间内没有进行读取,则会触发IdleState.READER_IDLE,然后在客户端3秒钟没进行读取后我关闭了通道,并期望channelInactive方法会被触发,但事实并非如此,为什么呢? 初始化程序
public class ServerInitializer extends ChannelInitializer<SocketChannel> {

    String TAG = "LOG: ";
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        System.out.println(TAG + "Starting ServerInitializer class...");
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
        pipeline.addLast("encoder", new ObjectEncoder());
        pipeline.addLast("idleStateHandler", new IdleStateHandler(6, 3, 0, TimeUnit.SECONDS));
        pipeline.addLast("handler", new ServerHandler());
    }
}

处理器

public class ServerHandler extends ChannelInboundHandlerAdapter {

    private String TAG = "LOG: ";

    public ServerHandler(){}

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Log.w(TAG,"New Client become connected, Sending a message to the Client. Client Socket is: " + ctx.channel().remoteAddress().toString());

        List<String> msg = new ArrayList<>();
        msg.add(0,"sample message 1");
        msg.add(1,"sample message 2");
        sendMessage(ctx, msg);
    }

    public void sendMessage(ChannelHandlerContext ctx, List message){
        ctx.write(message);
        ctx.flush();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        Log.w(TAG,"A Client become disconnected. Client Socket is: " + ctx.channel().remoteAddress().toString() + " id: " + (String.valueOf(ctx.channel().hashCode())));
         //COnnection id dead, do something here...
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object object) { // (2)
        Log.w(TAG, "CLIENT: "+ ctx.channel().remoteAddress().toString() + " SAYS: " + object);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        // Close the connection for that client  when an exception is raised.
        Log.e(TAG,"Something's wrong, CLIENT: "+ ctx.channel().remoteAddress().toString() + " CAUSE: " + cause.toString());
        ctx.close();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        Log.w(TAG,"LOLO");
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            if (e.state() == IdleState.READER_IDLE) {

                ctx.close(); //Closed the Channel so that the `channelInactive` will be trigger

            } else if (e.state() == IdleState.WRITER_IDLE) {

                ctx.writeAndFlush("ping\n"); //Send ping to client

            }
        }

    }
}

有人可以帮我吗?

2个回答

6

IdleStateHandler应该始终是您管道中的第一个处理程序。


我有同样的问题,需要为连接设置“keep-alive”时间。但在我的情况下,每个连接可能具有不同的keep-alive时间。我该怎么做? - Guerino Rodella

0

使用ReadTimeoutHandler代替IdleStateHandler,并覆盖exceptionCaught方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接