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