Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在netty消息中前置固定或可变长度的头_Java_Netty - Fatal编程技术网

Java 在netty消息中前置固定或可变长度的头

Java 在netty消息中前置固定或可变长度的头,java,netty,Java,Netty,我想为netty聊天程序的所有消息预先添加一个固定或可变长度的标题 现状 我正在建立一个简单的聊天;所有消息(当前)都使用and进行长度分隔,长度部分为2字节,到目前为止效果良好: +-------------+-------------------+ | <length> | <message> | | 13 | 'Yo, waz up?' | +-------------+---------------

我想为netty聊天程序的所有消息预先添加一个固定或可变长度的标题

现状 我正在建立一个简单的聊天;所有消息(当前)都使用and进行长度分隔,长度部分为2字节,到目前为止效果良好:

 +-------------+-------------------+  
 | <length>    | <message>         |  
 |    13       | 'Yo, waz up?'     | 
 +-------------+-------------------+ 
球门 目标是添加一个包含应用程序名称+版本的固定或可变标题,以过滤无效消息;此示例使用头文件“nChat v1.0”,10字节固定长度:

 --------------+--------------+-------------------+  
 | <length>    | <header>     | <message>         |  
 |    23       | 'nChat v1.0' | 'Yo, waz up?'     | 
 --------------+--------------+-------------------+ 
问题 我不确定向消息添加标题的最佳方法是什么。我假设需要一个自定义处理程序;我想到了两个想法:

  • 子类
    StringEncoder
    ,将标题前置到传出消息,按常规编码
  • 创建新的处理程序,类似于
    LengthFieldPrepender
    ,使用
    out.writeBytes(“nChat v1.0”.getBytes())序列化头文件。

我怀疑后一个选项是正确的,因为从原理上讲,标题与
LengthFieldPrepender
的功能没有什么不同;它支持可变长度的标题。我在这方面仍然是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;
      }
   }

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

我看还可以。但是,您可以减少对象分配的数量。例如,在
extractHeader(ByteBuf)
中,可以使用
ByteBuf.toString(offset,length,Charset)
读取标题字段。
pipeline.addLast(new LengthFieldBasedFrameDecoder (1024,0,2,0,2));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
   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());