2017-12-03 4 views
0

Ich lese die Dokumentation von IdleStateHandler und von meinem Server habe ich es wie aus der Dokumentation, implementiert, aber ich verstehe nicht, wie kann ich genau sagen, wenn der Client getrennt für Beispiel: Der Client verliert die WLAN-Verbindung.Netty: Verwenden von "IdleStateHandler", um Trennung zu erkennen

aus meinem Verständnis in meinem Handler, das Verfahren channelInactive() war Auslöser, wenn der Client getrennt werden, dann IdleStateHandler verwendet, wird die IdleState.READER_IDLE ausgelöst werden, wenn keine Lese für den angegebenen Zeitraum durchgeführt wurde, dann nach 3 Sekunden von keinem Lesen vom Client habe ich den Kanal geschlossen und habe erwartet, dass der channelInactive Trigger wird, aber es ist nicht, warum ?.

Initializer

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()); 
    } 
} 

Handler

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 

      } 
     } 

    } 
} 

Wer kann mir helfen

Antwort

1

IdleStateHandler immer der erste Handler in der Pipeline sein sollte.

0

Verwenden Sie ReadTimeoutHandler anstelle von IdleStateHandler, und überschreiben Sie die Methode exceptionCaught.

Verwandte Themen