---以下を編集
シリアル デバイスからメッセージを受信するために、実際にMina ProtocolCodecFilterを実装しています。
コーデックは複数の異なるメッセージ (pojos を含む) を指定し、実装が 99% の確率で正しく動作する場合でも、1 つのタイプのメッセージで問題が発生します:固定長を持たない唯一のメッセージです。最小の長さはわかりますが、最大の長さはわかりません。
これは私が受け取った例外メッセージです (重要な部分のみ):
org.apache.mina.filter.codec.ProtocolDecoderException: org.apache.mina.core.buffer.BufferDataException: dataLength: -2143812863 (Hexdump: 02 01 A2 02 01 A0 02)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:25
...
Caused by: org.apache.mina.core.buffer.BufferDataException: dataLength: -2143812863
at org.apache.mina.core.buffer.AbstractIoBuffer.prefixedDataAvailable(AbstractIoBuffer.java:2058)
at my.codec.in.folder.codec.MAFrameDecoder.doDecode(MAFrameDecoder.java:29)
at org.apache.mina.filter.codec.CumulativeProtocolDecoder.decode(CumulativeProtocolDecoder.java:178)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:241)
否定的な場合dataLength
もあれば、肯定的な場合もあります (この原因についての手がかりは見つかりませんでした)。
MAFrameDecoder :29は、CumulativeProtocolDecoder
のdoDecode()
メソッド (MAX_SIZE=4096)の実装の 2 番目の文です。
public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception
{
boolean result=false;
if(in.prefixedDataAvailable(4, MAX_SIZE)) //-->This is line 29
{
int length = in.getInt();
byte[] idAndData = new byte[length];
in.get(idAndData);
//do things, read from buffer, create message, out.write, etc
//if all has been correct, result=true
}
return result;
}
TCP スニファーを介してエラーをデバッグしているときに、複数のメッセージが同じ IoBuffer (in) に挿入されたときに例外がスローされることがわかりました。
Decoder
同じバッファ内で複数のメッセージを処理できないようです。しかし、前に言ったように、長さが固定されていないメッセージの問題もあります(関連性があるかどうかはわかりません)。他の doDecode 実装では、次のようなバッファを管理する別の方法を見てきました。
while (in.hasRemaining())
また
InputStream is=in.asInputStream();
とにかく、私は盲目的なステップを避けようとしているので、ここで質問しています. エラーを修正するだけでなく、その理由を知りたいです。
アドバイスをいただければ幸いです。: )
ps: バッファーを介してメッセージを送信するエンコーダーのautoExpandパラメーターはfalseです。
編集 10/11/2014
私は AbstractIoBuffer メソッドを調べていて、これを見つけました:
@Override
public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
if (remaining() < prefixLength) {
return false;
}
int dataLength;
switch (prefixLength) {
case 1:
dataLength = getUnsigned(position());
break;
case 2:
dataLength = getUnsignedShort(position());
break;
case 4:
dataLength = getInt(position());
break;
default:
throw new IllegalArgumentException("prefixLength: " + prefixLength);
}
if (dataLength < 0 || dataLength > maxDataLength) {
throw new BufferDataException("dataLength: " + dataLength);
}
return remaining() - prefixLength >= dataLength;
}
私が送信している prefixLength は 4 であるため、スイッチは最後の有効なケースに入ります。
dataLength = getInt(position());
その後、負の dataLength で BufferDataException をスローします。これは、AbstractIoBuffer のposition()
メソッドが負の値を返していることを意味します。
私は常に、nioBuffer がその位置パラメーターに負の値を保持することはできないと考えていました。なぜこれが起こっているのかの手がかりはありますか?