这是在MINA中编写ProtocolDecoder的正确方法吗?

时间:2010-05-22 18:06:42

标签: java apache nio apache-mina

public class CustomProtocolDecoder extends CumulativeProtocolDecoder{
byte currentCmd = -1;
int currentSize = -1;
boolean isFirst = false;
@Override
protected boolean doDecode(IoSession is, ByteBuffer bb, ProtocolDecoderOutput pdo) throws Exception {
        if(currentCmd == -1)
        {
            currentCmd = bb.get();
            currentSize = Packet.getSize(currentCmd);
            isFirst = true;
        }
        while(bb.remaining() > 0)
        {
            if(!isFirst)
            {
                currentCmd = bb.get();
                currentSize = Packet.getSize(currentCmd);
            }
            else
                isFirst = false;
            //System.err.println(currentCmd + " " + bb.remaining() + " " + currentSize);
            if(bb.remaining() >= currentSize - 1)
            {
                Packet p = PacketDecoder.decodePacket(bb, currentCmd);
                pdo.write(p);
            }
            else
            {
                bb.flip();
                return false;
            }
        }
        if(bb.remaining() == 0)
            return true;
        else
            return false;
}

}

有人发现此代码有什么问题吗?当一次接收到大量数据包时,即使只连接了一个客户端,其中一个可能会在最后被切断(例如12个字节而不是15个字节),这显然很糟糕。

2 个答案:

答案 0 :(得分:1)

我发现有点难以理解你在这里尝试解码的协议。在那里肯定看起来有点困惑;)

您是否在撰写需要同一连接的许多请求的内容?如果是这样,那就太好了,这就是Mina擅长的......

通常,我希望MINA解码器检查它是否有完整的消息,然后,如果没有,则将IoBuffer的指针返回到它在方法开始时保持的位置。

通常,完整的消息将由分隔符确定,或者可能是消息开头的长度字段。

api文档中提供的示例非常好。 它正在寻找Carriage Return + Line Break的分隔符:

http://mina.apache.org/report/trunk/apidocs/org/apache/mina/filter/codec/CumulativeProtocolDecoder.html

HTH

答案 1 :(得分:0)

在示例的帮助下弄清楚它 - 我有真假混淆,并没有意识到我应该跟踪输入缓冲区的位置。最重要的是,我不知道我不需要while循环。谢谢!

    protected boolean doDecode(IoSession is, ByteBuffer bb, ProtocolDecoderOutput pdo) throws Exception {
    int start = bb.position();
    currentCmd = bb.get();
    currentSize = Packet.getSize(currentCmd);
    //System.err.println(currentCmd + " " + bb.remaining() + " " + currentSize);
    if(bb.remaining() >= currentSize - 1)
    {
        Packet p = PacketDecoder.decodePacket(bb, currentCmd);
        pdo.write(p);
        if(bb.remaining() == 0)
            return false;
        else
            return true;
    }
    else
    {
        bb.position(start);
        return false;
    }
}