2017-12-03 82 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方法。