Netty ChannelRead方法

时间:2014-10-24 13:13:16

标签: netty serversocket channel

我是使用Netty Framework的新手。我遇到问题,我用Netty编写ServerSocket。 服务器的目标是从硬件接收消息。硬件每次都发送一个字节。服务器和硬件都有一个协议 - 每条消息都以'#'开头,以' *'结束。

@Sharable
class ServerHandler extends ChannelInboundHandlerAdapter {
   @Override
   public void channelRead(ChannelHandlerContext ctx, Object msg) {
       BytBuf in = (ByteBuf) msg;
       CharBuffer charBuffer = CharBuffer.allocate(100);
       String recedata ;
       byte tmp;
       try {
           while (in.isReadable()) {
             tmp = in.readByte();
             if (tmp != 42) {    
                charBuffer.append((char) tmp);
               // System.out.println(String.valueOf(charBuffer.array()));
             } else {              //means receive a byte '*'
                charBuffer.append('*');
                count = 0; 
                recData = String.valueOf(charBuffer.array());
                logger.debug("receive message is " + recData);
             } 
       }catch(Exception e){
             e.printStackTrace();
       }

   }     
}

然而,出现问题。当硬件首次发送#abcd时,服务器将存储#abcd 然后硬件可能会发送efg*。由于Netty是异步和事件驱动的,因此方法ChannelRead()将从头到尾运行。因此将打印efg*,而不是#abcdefg*

我想了很多。最后,我有一个想法。我使用类似AttribueKey的{​​{1}}来绑定一个数组,以便将所有接收到的字节与通道一起存储。然后我从数组中得到ThreadLocal。但阵列非常大。这不是一个好方法。 你有更好的方法来解决我的问题吗?谢谢你的帮助

1 个答案:

答案 0 :(得分:1)

查看Netty用户指南 - 处理基于流的传输。消息可能会碎片化 - 因此在您的情况下,它可能会收到#ab;#abcd"然后是" efg *"。由于每次都要分配一个CharBuffer,原始的CharBuffer包含"#abcd"。在第二个方法调用中,CharBuffer包含" efg *"。

解决方案是使用ByteToMessageDecoder。 decode()将被重复调用(通过Netty框架),直到ByteBuf为空(即,您的解码代码将其清空)。所以你在decode()中可以做的就是继续返回,直到" in" ByteBuf包含* char。完成后,将ByteBuf的内容写入" out"列表从开头#到*。 *之后的任何剩余字节将在ByteBuf中保留,并且该过程将继续。