2012-02-15 25 views
5

Mam zabawny serwer Netty i próbuję wysyłać wiadomości do klientów, gdy nic się nie wydarzy na ich kanałach. Testuję to przez telnetowanie się do serwera, pisanie wiadomości, a następnie wysyłanie czegokolwiek, ale nie dostaję żadnego echa!Problemy z Netty IdleStateHandler - czy testuję to w niewłaściwy sposób?

konsoli:

>>telnet localhost 6969 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
>>foo 
Did you say 'foo'? 

MyPipelineFactory.java

public class MyPipelineFactory implements ChannelPipelineFactory { 
    private final Timer timer; 
    private static final ChannelHandler stringDecoder = new StringDecoder(); 
    private static final ChannelHandler stringEncoder = new StringEncoder(); 
    private final ChannelHandler idleStateHandler; 

    public MyPipelineFactory(Timer t) { 
     this.timer = t; 
     this.idleStateHandler = new IdleStateHandler(timer, 5, 5, 5); 
    } 

    public ChannelPipeline getPipeline() { 
     // create default pipeline from static method 
     ChannelPipeline pipeline = Channels.pipeline(); 
     pipeline.addLast("idleStateHandler", this.idleStateHandler); // heartbeat 
     pipeline.addLast("framer", new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter())); 
     //pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024,0,1)); // get header from message 
     pipeline.addLast("stringDecoder", stringDecoder); 
     pipeline.addLast("stringEncoder", stringEncoder); 
     pipeline.addLast("ServerHandler", new ServerHandler()); // goes at the end 

     return pipeline; 
    } 
} 

HeartbeatHandler.java

public class HeartbeatHandler extends IdleStateAwareChannelHandler { 

    @Override 
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) { 
     if (e.getState() == IdleState.READER_IDLE) { 
      System.out.println("Reader idle, closing channel"); 
      //e.getChannel().close(); 
      e.getChannel().write("heartbeat-reader_idle"); 
     } 
     else if (e.getState() == IdleState.WRITER_IDLE) { 
      System.out.println("Writer idle, sending heartbeat"); 
      e.getChannel().write("heartbeat-writer_idle"); 
     } 
     else if (e.getState() == IdleState.ALL_IDLE) { 
      System.out.println("All idle, sending heartbeat"); 
      e.getChannel().write("heartbeat-all_idle"); 
     } 
    } 
} 

stałej:

Zapomniałem mieć HeartbeatHandler, który wymaga IdleStateHandler (ta część nie była dla mnie oczywista). To działa.

public class MyPipelineFactory implements ChannelPipelineFactory { 
    private final Timer timer; 
    private static final ChannelHandler stringDecoder = new StringDecoder(); 
    private static final ChannelHandler stringEncoder = new StringEncoder(); 
    private final ChannelHandler idleStateHandler; 
    private final ChannelHandler heartbeatHandler; 

    public MyPipelineFactory(Timer t) { 
     this.timer = t; 
     this.idleStateHandler = new IdleStateHandler(timer, 5, 5, 5); 
     this.heartbeatHandler = new HeartbeatHandler(); 
    } 

    public ChannelPipeline getPipeline() { 
     // create default pipeline from static method 
     ChannelPipeline pipeline = Channels.pipeline(); 
     pipeline.addLast("idleStateHandler", this.idleStateHandler); 
     pipeline.addLast("heartbeatHandler", this.heartbeatHandler); // heartbeat 
     pipeline.addLast("framer", new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter())); 
     //pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024,0,1)); // get header from message 
     pipeline.addLast("stringDecoder", stringDecoder); 
     pipeline.addLast("stringEncoder", stringEncoder); 
     pipeline.addLast("ServerHandler", new ServerHandler()); // goes at the end 

     return pipeline; 
    } 
} 

Odpowiedz

9

Tęskniłeś, aby dodać HeartbeatHandler na ChannelPipeline. Musisz dodać IdleStateHandler AND HeartbeatHandler do ChannelPipeline, aby to działało. Odpowiedź

+1

ah, to nie było jasne z dokumentów, że potrzebuję obu.dzięki znowu – nflacco

+0

czy to możliwe, że HeartbeatHandler nie jest już potrzebny w 3.5.9? –

+0

Nadal potrzebujesz zarówno –

1

Norman jest naprawdę pomocny, ale to, co chciałbym podkreślić inną rzecz: idleStateHandler i heartbeatHandler należy kanał specyficzny, więc w PipeLineFactory, nie należy konstruować te dwie ładowarki jako członków prywatnych, ale trzeba utworzyć nowe w metodzie getPipeline(). Masz również mapę kanałów, aby zapisać skonstruowane kanały, jeśli chcesz je zwolnić, lepiej zatrzymać zegar, aby zwolnić zasoby.

+0

od IdleStateHandler można udostępniać Nie sądzę, że trzeba utworzyć nowe wystąpienie dla każdego potoku. – WorM