在netty消息中添加固定或可变长度头

时间:2014-12-29 22:19:09

标签: java netty

我想为netty聊天程序的所有消息添加固定或可变长度标头。

当前状态

我正在建立一个简单的聊天;所有消息(当前)都使用LengthFieldPrependerLengthFieldBasedFrameDecoder length 分隔,长度部分为2个字节,到目前为止这个工作正常:

 +-------------+-------------------+  
 | <length>    | <message>         |  
 |    13       | 'Yo, waz up?'     | 
 +-------------+-------------------+ 

..和管道

//inbound
pipeline.addLast(new LengthFieldBasedFrameDecoder (1024,0,2,0,2));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
//outbound
pipeline.addLast(new LengthFieldPrepender(2));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));

目标

目标是添加包含应用名称+版本的固定或变量标头,以过滤掉无效消息;此示例使用标头'nChat v1.0',固定长度为10个字节:

 --------------+--------------+-------------------+  
 | <length>    | <header>     | <message>         |  
 |    23       | 'nChat v1.0' | 'Yo, waz up?'     | 
 --------------+--------------+-------------------+ 

调整入站管道以容纳标题应该不是问题,但我不希望标题被剥离,所以我将initialBytesToStrip留在了2

pipeline.addLast(new LengthFieldBasedFrameDecoder (1024,0,2,0,2));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));

问题

我不确定在邮件中添加标头的最佳方法是什么。我假设需要自定义处理程序;脑海中浮现出两个想法:

  • 子类StringEncoder,将标头添加到外发邮件中,照常编码。
  • 使用LengthFieldPrepender
  • 创建新的处理程序,类似于out.writeBytes("nChat v1.0".getBytes()),序列化标题

我怀疑后一种选择是正确的,因为标题在本质上与它正在做的事情上的LengthFieldPrepender没有区别。

1 个答案:

答案 0 :(得分:0)

这是我想出的;它支持可变长度标头。我仍然是一个n00b,欢迎评论:-D

   public class HeaderFieldEncoder extends MessageToByteEncoder<ByteBuf> { 
      public HeaderFieldEncoder(String header){
         this.header = header;
      }     
      @Override
      protected void encode(
         ChannelHandlerContext ctx,
         ByteBuf msg,
         ByteBuf out
      )throws Exception {                           
         //header = "nChat v1.0"
         ByteBuf headerBuf = Unpooled.copiedBuffer(
            header.getBytes(charset));                                    
         out.writeBytes(headerBuf);
         out.writeBytes(msg, msg.readerIndex(), msg.readableBytes());      
      }           
   }


   public class HeaderFieldDecoder extends MessageToMessageDecoder<ByteBuf> {
      public HeaderFieldDecoder(String header){
         this.header = header;
      }
      @Override
      protected void decode(
         ChannelHandlerContext ctx,
         ByteBuf msg,
         List<Object> out
      )throws Exception {
         String extractedHeader = extractHeader(msg);
         //if desired, validate header
         //if(!header.equals(extractedHeader)
         String content = msg.toString(charset);
         out.add(content);         
      }

      private String extractHeader(ByteBuf msg){
         String headerField = null;
         if(msg.readableBytes() >= header.length()){
            byte[] headerBytes = new byte[header.length()];
            msg.readBytes(headerBytes, 0, header.length());
            headerField = new String(headerBytes, charset);
         }
         return headerField;
      }
   }

工作渠道:

String header = "nChat v1.0";
//INBOUND 
pipeline.addLast(new LengthFieldBasedFrameDecoder(1024,0,2,0,2));
pipeline.addLast(new HeaderFieldDecoder(header));
pipeline.addLast(new StringDecoder());

//OUTBOUND
pipeline.addLast(new LengthFieldPrepender(2)); 
pipeline.addLast(new HeaderFieldEncoder(header));
pipeline.addLast(new StringEncoder()); 

你怎么看;这有效吗?我是否正确清理资源?