2015-11-06 2796 views
1

我使用LengthFieldBasedFrameDecoder來發送和接收byte[]但客戶端寫入後得到錯誤java.nio.channels.ClosedChannelException在Netty中發送字節數組

這裏是管道工廠;

@Override 
public ChannelPipeline getPipeline() throws Exception { 

    String charSet = EvamProperties.charSet.get(); 
    ChannelPipeline pipeline = Channels.pipeline(); 

    pipeline.addLast("framer", new LengthFieldBasedFrameDecoder(1000000,0,4,0,4));//16KB 
    pipeline.addLast("decoder", new OneToOneDecoder() { 
     @Override 
     protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception { 

      if (!(o instanceof ChannelBuffer)) { 
       return o; 
      } 

      ChannelBuffer buffer = (ChannelBuffer) o; 

      int length = buffer.readInt(); 
      byte[] bytes = new byte[length]; 
      buffer.readBytes(bytes); 

      return bytes; 
     } 
    }); 
    pipeline.addLast("encoder", new OneToOneEncoder() { 
     @Override 
     protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception { 

      if(!(o instanceof byte[])) { 
       return o; 
      } 

      ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); 
      buffer.writeInt(((byte[]) o).length); 
      buffer.writeBytes((byte[])o); 

      return buffer; 
     } 
    }); 
    pipeline.addLast("handler", new RawEventServerHandler()); 
    return pipeline; 

} 

客戶端以這種方式寫入;

channel.write(eventStr.getBytes()); 

在這段代碼中用於調試目的發送的數據是字符串,但我不能使用StringDecoder。

請問LenghtFieldBasedDecoder發送和接收是否正確byte[],如果沒有,我該怎麼辦?

編輯:

我發現另一個線程實際關閉通道使java.nio.channels.ClosedChannelException解決,但我仍然渴望去學習這種工作的最佳實踐。

+1

首先,如果使用Netty 4.x,則需要刷新某處(例如'writeAndFlush')。其次,'ClosedChannelException'意味着你試圖在通道已經關閉時讀取或寫入通道。可能有幾個原因。你在客戶端和服務器兩端的RawEventServerHandler是什麼? –

+0

謝謝你看到我的編輯。 –

回答

1

我看到根據您的問題,3種不同的用途:

  1. 傳入字節表示的存儲在幀某些特定length幀,您需要捕獲一個幀byte[length],並將其轉移到用戶
  2. 傳入字節表示固定length幀,需要捕獲幀作爲byte[length]並將其傳送到所述用戶
  3. 傳入字節不表示任何幀和用戶可以處理任意長度byte[]陣列

在(1)的LengthFieldBasedFrameDecoder是個不錯的選擇的情況下,它允許您捕獲基於存儲在幀中的長度的幀。如果(2)FixedLengthFrameDecoder應該足夠,如果你知道所有的幀都具有相同的大小。在(3)你不需要任何特殊的解碼器的情況下,所有可讀的字節可以從傳入的ByteBuf中獲取並傳送到下一個處理程序,但我不確定在實際應用程序中該方法有多大用處,因爲大多數情況下,會處理某些特定類型/大小的消息,Netty不能保證消息的分割準確度,一個消息可以以N個不同的分塊出現。

還有ReplayingDecoder如果您想解碼傳入的字節並跳過捕獲步驟,則對於案例(1-2)很有用。