2013-08-30 3 views
0

У меня следующая ситуация:Нетти: channel.write висит на разъединение

Новый соединительный канал открывается таким образом:

ClientBootstrap bootstrap = new ClientBootstrap(
      new OioClientSocketChannelFactory(Executors.newCachedThreadPool())); 

    icapClientChannelPipeline = new ICAPClientChannelPipeline();   
    bootstrap.setPipelineFactory(icapClientChannelPipeline); 
    ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); 
    channel = future.awaitUninterruptibly().getChannel(); 

Это работает, как ожидалось.

Материал написан на канале следующим образом:

channel.write(chunk) 

Это также работает, как ожидается, когда соединение с сервером все еще жив. Но если сервер идет вниз (машина переходит в автономный режим), вызов зависает и не возвращается.

Я подтвердил это, добавив записи журнала до и после channel.write(chunk). Когда соединение прерывается, отображается только оператор журнала.

  1. Что вызывает это? Я думал, что эти вызовы все асинхронны и сразу возвращаются? Я также пробовал с NioClientSocketChannelFactory, такое же поведение.

  2. Я пытался использовать channel.getCloseFuture(), но слушатель никогда не вызывается, я попытался проверить канал перед записью с channel.isOpen(), channel.isConnected() и channel.isWritable() и они всегда верны ...

  3. Как обойти это? Исключение не выбрасывается, и ничего действительно не происходит ... Некоторые вопросы, такие как this one и this one, показывают, что невозможно обнаружить отключение канала без биения. Но я не могу выполнить биение, потому что я не могу изменить серверную сторону.

Окружающая среда: Нетти 3, JDK 1,7

ответ

0

Хорошо, я решил этот на моей прошлой неделе я добавлю ответ на Комплектность.

Я был неправ в 3., потому что я думал, что мне придется изменить как клиент, так и серверную сторону на мгновение. Как описано in this question, для этой цели вы можете использовать IdleStateAwareHandler. Я реализовал это следующим образом:

IdleStateAwareHandler:

public class IdleStateAwareHandler extends IdleStateAwareChannelHandler { 

    @Override 
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) { 
     if (e.getState() == IdleState.READER_IDLE) { 
      e.getChannel().write("heartbeat-reader_idle"); 
     } 
     else if (e.getState() == IdleState.WRITER_IDLE) { 
      Logger.getLogger(IdleStateAwareHandler.class.getName()).log(
        Level.WARNING, "WriteIdle detected, closing channel"); 
      e.getChannel().close(); 
      e.getChannel().write("heartbeat-writer_idle"); 
     } 
     else if (e.getState() == IdleState.ALL_IDLE) { 
      e.getChannel().write("heartbeat-all_idle"); 
     } 
    } 
} 

Трубопроводной:

public class ICAPClientChannelPipeline implements ICAPClientPipeline { 

     ICAPClientHandler icapClientHandler; 
     ChannelPipeline pipeline; 

     public ICAPClientChannelPipeline(){ 
      icapClientHandler = new ICAPClientHandler(); 
     pipeline = pipeline(); 
      pipeline.addLast("idleStateHandler", new IdleStateHandler(new HashedWheelTimer(10, TimeUnit.MILLISECONDS), 5, 5, 5)); 
      pipeline.addLast("idleStateAwareHandler", new IdleStateAwareHandler()); 
      pipeline.addLast("encoder",new IcapRequestEncoder()); 
      pipeline.addLast("chunkSeparator",new IcapChunkSeparator(1024*4)); 
      pipeline.addLast("decoder",new IcapResponseDecoder()); 
      pipeline.addLast("chunkAggregator",new IcapChunkAggregator(1024*4)); 
      pipeline.addLast("handler", icapClientHandler);    
     } 

     @Override 
    public ChannelPipeline getPipeline() throws Exception { 
      return pipeline; 
    }      
} 

Это обнаруживает любые операции чтения или записи в состояние ожидания на канале через 5 секунд. Как вы можете видеть, это немного специфично для ICAP, но это не имеет значения для вопроса.

реагировать на ожидании событие мне нужен следующий слушатель:

channel.getCloseFuture().addListener(new ChannelFutureListener() { 
    @Override 
    public void operationComplete(ChannelFuture future) throws Exception { 
      doSomething(); 
    } 
}); 
Смежные вопросы