minaフレームワークCumulativeProtocolDecoder.doDecode法の浅い分析
19764 ワード
注釈コード37行をテストし、38行を開きます.
サーバーが正常に起動し、デバイスの接続が正常であることを確認します.デバイスはクライアントで、3秒ごとにサーバーにハートビートを送信します
シミュレーションネットワークは短くて通じず、複数のパケットが同時に到着し、パケットが付着した場合:ネットワーク線を30秒抜いて、ネットワーク線を挿入します.
コードは次のとおりです.
次のように印刷
説明ネットワーク線を挿入した後、ログを印刷しません.(アナログで、すぐに印刷する場合もあります)約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上位コードに戻る
ログ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バイトを加えて完成したパケットを組み合わせることができます.
サーバーが正常に起動し、デバイスの接続が正常であることを確認します.デバイスはクライアントで、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バイトを加えて完成したパケットを組み合わせることができます.