2017-12-03 78 views
0

我读的IdleStateHandler文件,并从我的服务器我实现了它与从文档, 但我不我如何能确切地告诉如果客户端断开连接理解例如客户端丢失了Wifi连接。的Netty:使用`IdleStateHandler`检测断线

从我的理解,我的处理程序中,该方法channelInactive()被触发,当客户端断开连接, 然后使用IdleStateHandler,当在规定的时间段, 然后3秒后未进行读取的IdleState.READER_IDLE将被触发没有从客户端读取我关闭了频道,并期待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 

      } 
     } 

    } 
} 

任何人都可以帮我

回答

1

IdleStateHandler应始终在您的管道第一处理器。

0

使用ReadTimeoutHandler而不是IdleStateHandler并重写exceptionCaught方法。