从LengthFieldBasedFrameDecoder返回的缓冲区太小 [英] Buffer Returned from LengthFieldBasedFrameDecoder too small
问题描述
我目前正在评估Netty,以处理Java客户端与C ++服务器集成的套接字通信.消息传递协议具有以下结构-
I am currently evaluating Netty to handle socket comms for a Java client to integrate with a C++ server. The messaging protocol has the following structure -
- (类型)(子类型)(长度)(MessageBody)大小
- < 4bytes>< 4bytes>< 4bytes>< ...> -长度包括标题.
- (Type)(SubType)(Length)(MessageBody) with size
- <4bytes><4bytes><4bytes><...> - The Length includes the header.
在Netty api I子类LengthFieldBasedFrameDecoder之后,它接收有效的完整数据包,然后根据接收的类型对每个数据包进行解码.从我正在使用的文档中-
Following the Netty api I subclass LengthFieldBasedFrameDecoder to receive a valid full packet and then decode each packet depending on the type received. From docs I'm using -
- lengthFieldOffset = 8
- lengthFieldLength = 4
- lengthAdjustment = -12(= HDR1 + LEN的长度,负数)
- initialBytesToStrip = 0
它可以正常工作约5分钟(我每5秒左右收到一条消息),然后解码事件包含一个ChannelBuffer,该ChannelBuffer短于消息的大小. (崩溃之前,我已经多次收到此消息).然后,我显然在我的内部解码代码中得到了BufferUnderflowException.难道我做错了什么?使用LengthFieldBasedFrameDecoder时,是否应该保证消息的缓冲区大小正确?
It works fine for about 5 minutes (I'm getting one message every 5 seconds or so) and then the decode event contains a ChannelBuffer that is much shorter than the size of the message. (I have received this message multiple times before the crash). I then obviously get an BufferUnderflowException in my internal decode code. Am I doing something wrong? Should I be guaranteed the correct sized buffer for the message when using LengthFieldBasedFrameDecoder?
LengthFieldBasedFrameDecoder类-
LengthFieldBasedFrameDecoder class -
public class CisPacketDecoder extends LengthFieldBasedFrameDecoder
{
public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment,
initialBytesToStrip);
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf)
throws Exception
{
CisMessage message = null;
int type = buf.getInt(0); //Type is always first int
CisMessageType messageType = CisMessageType.fromIntToType(type);
if(messageType != null)
{
message = messageType.getObject();
if(message != null)
{
message.decode(buf.toByteBuffer());
}
else
{
System.out.println("Unable to create message for type " + type);
}
}
//mark the Channel buf as read by moving reader index
buf.readerIndex(buf.capacity());
return message;
}
}
并在此处实例化.
public class PmcPipelineFactory implements ChannelPipelineFactory
{
@Override
public ChannelPipeline getPipeline() throws Exception
{
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("encoder", new CisPacketEncoder());
pipeline.addLast("decoder", new CisPacketDecoder(1024, 8, 4, -12, 0));
pipeline.addLast("handler", new MsgClientHandler());
return pipeline;
}
}
推荐答案
您需要调用super.decode(..)并在您的encode(..)方法中对返回的ChannelBuffer进行操作.
You need to call super.decode(..) and operate on the returned ChannelBuffer in your decode(..) method.
所以会是这样;
public class CisPacketDecoder extends LengthFieldBasedFrameDecoder {
public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment,
initialBytesToStrip);
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf)
throws Exception {
// THIS IS IMPORTANT!!!!!
ChannelBuffer decoded = (ChannelBuffer) super.decode(ctx, channel, buf);
if (decoded == null) {
return null;
}
// NOW ONLY OPERATE ON decoded
CisMessage message = null;
int type = decoded.getInt(0); //Type is always first int
CisMessageType messageType = CisMessageType.fromIntToType(type);
if(messageType != null) {
message = messageType.getObject();
if(message != null) {
message.decode(decoded.toByteBuffer());
} else {
System.out.println("Unable to create message for type " + type);
}
}
return message;
}
}
请务必检查大写注释.
这篇关于从LengthFieldBasedFrameDecoder返回的缓冲区太小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!