2012-02-15 117 views
5

我有一個玩具Netty服務器,並試圖發送心跳消息給客戶端,當他們的頻道沒有發生任何事情時。我正在通過telnet到服務器,寫信息然後不發送任何東西來測試這個,但是我沒有聽到任何信息!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"); 
     } 
    } 
} 

修正:

我忘了有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

您錯過了在ChannelPipeline中添加HeartbeatHandler。您需要將IdleStateHandler HeartbeatHandler添加到ChannelPipeline以使其工作。

+1

啊,從文檔中我並不清楚,我需要兩個。再次感謝 – nflacco 2012-02-15 16:34:57

+0

是否可以在3.5.9中不再需要HeartbeatHandler? – 2012-10-31 08:46:50

+0

您仍然需要 – 2012-10-31 17:55:15

1

Norman的回答是一個非常有用的,但我想指出另一件事情:idleStateHandler和heartbeatHandler應該是通道特定的,所以在PipeLineFactory中,您不應該將這兩個處理程序構造爲私有成員,但需要在getPipeline()方法中創建新的。您還可以通過頻道圖保存構建的頻道,如果您需要發佈頻道,最好還是停止計時器以釋放資源。

+0

因爲IdleStateHandler是可共享的我不認爲你需要爲每個管道創建一個新的實例。 – WorM 2017-12-12 15:36:55

相關問題