2012-02-15 4 views
5

У меня есть игрушечный Netty-сервер, и я пытаюсь послать сообщения о сердцебиении клиентам, когда на их каналах ничего не произошло. Я тестирую это путем telnetting на сервер, пишу сообщение, а затем ничего не отправляя, но я не слышу!Проблема с Netty IdleStateHandler - я проверяю это неправильно?

консоли:

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

Fixed:

Я забыл иметь HeartbeatHandler, для которого требуется IdleStateHandler (эта часть для меня не была очевидна). Это работает.

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

ответ

9

Вы пропустили добавление HeartbeatHandler в ChannelPipeline. Вам нужно добавить IdleStateHandler И HeartbeatHandler на ChannelPipeline, чтобы он работал.

+1

ах, это было непонятно из документов, что мне нужно и то, и другое. – nflacco

+0

может быть, что HeartbeatHandler больше не нужен в 3.5.9? –

+0

Вам все еще нужны как –

1

Ответ Norman действительно полезен, но я хотел бы указать на другое: idleStateHandler и heartbeatHandler должны быть специфичными для канала, поэтому в PipeLineFactory вы не должны создавать эти два обработчика как частные члены, но нужно создавать новые в методе getPipeline(). У вас также есть карта каналов для сохранения построенных каналов, если вам нужно их выпустить, лучше также остановить таймер, чтобы освободить ресурсы.

+0

Поскольку IdleStateHandler является доступным, я не думаю, что вам нужно создать новый экземпляр для каждого конвейера. – WorM