2013-08-24 33 views
1

我正在使用Netty 4.0.7.Final編寫一個服務器,它通過TCP接收圖像(大小:〜10k)。 我修改了Netty的示例echo客戶端處理程序,只是將文件讀入字節,然後將其發送到我的Netty服務器。通過Netty發送TCP數據包,Netty將數據分成不同的數據包?

public EchoClientHandler(int firstMessageSize) throws IOException { 
    File image = new File("google.jpeg"); 
    byte[] imageBytes = FileUtils.readFileToByteArray(image); 
    byte[] bytes = Base64.encodeBase64(imageBytes); 
    String base64 = new String(bytes); 
    //System.out.println("base64="+ base64); 
    firstMessage = Unpooled.copiedBuffer(base64, CharsetUtil.UTF_8); 
} 

我的測試圖像是9K,我可以看到整個圖像被經由Netty的發送登錄

io.netty.handler.logging.LoggingHandler logMessage 
INFO: [id: 0x132baef0, /127.0.0.1:49710 => localhost/127.0.0.1:2112] WRITE(11964B) 

然而,當Netty的服務器接收到該消息,它似乎是將所述消息成兩個分組,所述第一分組是1024個字節,並且第二個是10940個字節,這將增加高達1024 + 10940 = 11964個字節(圖像的總大小)

2013-08-24 22:56:33,700 [nioEventLoopGroup-3-1] INFO MessageDecoder - capacity = 1024 
2013-08-24 22:56:33,700 [nioEventLoopGroup-3-1] INFO MessageDecoder - readable bytes = 1024 
2013-08-24 22:56:33,709 [nioEventLoopGroup-3-1] INFO MessageDecoder - capacity = 16384 
2013-08-24 22:56:33,710 [nioEventLoopGroup-3-1] INFO MessageDecoder - readable bytes = 10940 

下面是我的解碼器升ooks一樣(雖然我懷疑解碼器有什麼關係呢,它看起來像Netty的是處理這一點,甚至達到解碼器之前)

public class MessageDecoder extends ByteToMessageDecoder { 

private static final Logger LOGGER = LoggerFactory.getLogger(MessageDecoder.class); 

@Override 
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 
    // Convert to String first 
    LOGGER.info("capacity = " + in.capacity()); 
    LOGGER.info("readable bytes = " + in.readableBytes()); 
    String rawString = in.readBytes(in.readableBytes()).toString(CharsetUtil.UTF_8);  
    LOGGER.info("Received base64 String={}", rawString); 
} 

我也嘗試過大量的文件,它看起來的Netty總是將一個消息到1024字節的數據包+文件的其餘部分的任何大小?

我想知道爲什麼Netty正在這樣做?有沒有辦法一次性獲得完整的數據包?

非常感謝。

+0

我不認爲Netty正在這樣做。這與tcp/ip的工作方式有關。這取決於您的消息正在經過哪些路由器。例如,任何WLAN上的MTU(最大傳輸單元)大約爲1400字節。 – Szobi

+0

Netty不會分割任何東西,但是IP和TCP會分割。 – EJP

+0

非常感謝,我能夠使用DelimiterBasedFrameDecoder(自帶Netty)解析並指定最大幀大小 – littlejedi

回答

2

如果您想從處理程序中抽象出碎片,則需要對消息進行構建。這可以通過發送時使用LengthFieldPrepender和接收時使用LengthFieldBasedFrameDecoder來輕鬆完成。這可以確保您的消息解碼器只能看到表示完整消息的字節緩衝區。

請注意,您的幀處理程序應該在您的ChannelPipeline中首先使用,除非您還在使用SSL處理程序和/或壓縮處理程序(在這種情況下應首先使用SSL,然後使用壓縮,然後使用幀處理程序)。首先在管道中意味着處理程序將首先處理和入站事件,並最後處理出站事件。