minaフレームワークCumulativeProtocolDecoder.doDecode法の浅い分析


注釈コード37行をテストし、38行を開きます.
サーバーが正常に起動し、デバイスの接続が正常であることを確認します.デバイスはクライアントで、3秒ごとにサーバーにハートビートを送信します
シミュレーションネットワークは短くて通じず、複数のパケットが同時に到着し、パケットが付着した場合:ネットワーク線を30秒抜いて、ネットワーク線を挿入します.
コードは次のとおりです.
package mina;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Arrays;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class Test {
    public static void main(String[] args) throws IOException {
        final byte[] key = { (byte) 0xb9, (byte) 0xda, 0x5e, 0x15, 0x46, 0x57, (byte) 0xa7, (byte) 0x8d, (byte) 0x9d,
                (byte) 0x84, (byte) 0x90, (byte) 0xd8, (byte) 0xab, 0x00, (byte) 0x8c, (byte) 0xbc, (byte) 0xd3, 0x0a,
                (byte) 0xf7, (byte) 0xe4, 0x58, 0x05, (byte) 0xb8, (byte) 0xb3, 0x45, 0x06, (byte) 0xd0, 0x2c, 0x1e,
                (byte) 0x8f, (byte) 0xca, 0x3f };

        NioSocketAcceptor acceptor = new NioSocketAcceptor();
        acceptor.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ProtocolEncoderAdapter() {
            @Override
            public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
                System.out.println(" :" + message);
            }
        }, new CumulativeProtocolDecoder() {
            @Override
            protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
                System.out.println();
                System.out.println(" :" + in.limit());
                System.out.println();
                IoBuffer ioBuffer = getContext(session).getIoBuffer();
                //IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);

                while (in.hasRemaining()) {
                    byte b = in.get();
                    ioBuffer.put(b);
                    System.out.print("【"+b+"】");

                    if (b != 0x03 && b != 0x04) {
                        continue;
                    }

                    byte[] array = ioBuffer.array();

                    if (array[0] != 0x02) {
                        System.out.println();
                        System.out.println("=======================================");
                        System.out.println(" " + ByteUtil.toHexStr(array));
                        System.out.println("=======================================");
                        throw new RuntimeException("================ ================");
                    }

                    array = Arrays.copyOfRange(array, 1, ioBuffer.position() - 2);
                    int temp1 = array.length / 32;
                    int temp2 = array.length % 32;
                    for (int i = 0; i < temp1; i++) {
                        for (int j = 0; j < 32; j++) {
                            array[i * 32 + j] ^= key[j];
                        }
                    }
                    for (int j = 0; j < temp2; j++) {
                        array[temp1 * 32 + j] ^= key[j];
                    }

                    System.out.println("");
                    System.out.println("=======================================");
                    System.out.println(" :" + new String(array));
                    System.out.println("=======================================");

                    out.write(new String(array));
                    ioBuffer.clear();
                    System.out.println(" true");
                    return true;
                }

                System.out.println(" false");
                return false;
            }

            private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");

            public Context getContext(IoSession session) {
                Context ctx = (Context) session.getAttribute(CONTEXT);
                if (ctx == null) {
                    ctx = new Context();
                    session.setAttribute(CONTEXT, ctx);
                }
                return ctx;
            }

            class Context {
                private IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);

                public IoBuffer getIoBuffer() {
                    return ioBuffer;
                }
            }
        }));
        acceptor.setHandler(new IoHandlerAdapter() {

            @Override
            public void messageReceived(IoSession session, Object message) throws Exception {
                super.messageReceived(session, message);
            }
        });

        acceptor.bind(new InetSocketAddress(3333));
    }
}

次のように印刷

 :53

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

 :256

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

 :256

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

 :256

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

 :256

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

 :256

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】 false

 :433

【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 BD,C5,67,F8,D4,E9,3D,00,03,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
=======================================

 :53

【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
 :device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
 true

説明ネットワーク線を挿入した後、ログを印刷しません.(アナログで、すぐに印刷する場合もあります)約20秒後、5、60行のログが瞬時に届きます.
ハートビートパケットは0 x 02で始まり、0 x 03で終わり、長さは53です.
ログ2行目:長さ53で、このパッケージが正常であることを示します.
ログの10行目:長さは256で、IoBuffer inがキャッシュから256バイトを一度に読み出すことを示し、4つのハートビートパケットと半分のハートビートパケットの長さである.コード:41行、毎回1バイト42行を取り、ioBuffer 45行にバイトを保存し、完全なパケットを取らなければioBuffer 60行にバイトを保存し続け、データ79行を復号し、true上位コードに戻る
protected CumulativeProtocolDecoder() {
    }
    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        if (!session.getTransportMetadata().hasFragmentation()) {
            while (in.hasRemaining()) {
            /**
         in 53 , ( 256), doDecode true, doDecode。CumulativeProtocolDecoder.decode(..) , , , decode 。 : synchronized (session) {
                    decoder.decode(session, in, decoderOut);
                }
            */
                if (!doDecode(session, in, out)) {
                    break;
                }
            }
            return;
        }

        boolean usingSessionBuffer = true;
        IoBuffer buf = (IoBuffer) session.getAttribute(BUFFER);

ログ18行目:inの256の53の位置から53バイトを読み出し続け、trueに戻る
ログ26行目:inの256の106の位置から53バイトを読み出し続け、trueに戻る
ログ34行目:inの256の159から53バイトを読み出し続け、trueを返します.
ログ34行目:inの256の212の位置から53バイトを読み出し続け、trueに戻る
ログ42行目:inの256の212の位置から44バイトの読み出しを継続し、false CumulativeProtocolDecoder(){}public void decode(IoSession session,IoBuffer in,ProtocolDecoderOutput out)throws Exception{if(!session.getTransportMetadata(){while(in.hasRemaining(){/**falseを返し、本方法の実行が完了したことを示す.新しいパッケージがあれば実行している.*/if(!doDecode(session,in,out){break;}return; }
ログ42行目:今回の長さ433(前回のハートビートパケットの9バイト+新しい8ハートビートパケットの長さ)test.java.38行で再作成されたIoBufferは、0 x 03で切り取った場合、9バイト分の長さになります.そのためIoBufferをセッションに入れる必要があり、前回取ったパケットに今回の9バイトを加えて完成したパケットを組み合わせることができます.