Nettyシリーズの:nettyの怠け者コードデコーダ
8285 ワード
概要
Nettyが強力なのは、非常に有用な符号化デコーダがたくさん内蔵されているためで、これらの符号化デコーダを使用することで、非常に強力なアプリケーションを簡単に構築することができます.今日はnettyの中で最も基本的な内蔵符号化デコーダについてお話しします.
Nettyに内蔵されたエンコーダ
nettyのパッケージを導入すると、nettyにはnetty-codecで始まるartifactIdがたくさんあることがわかります.統計すると、こんなにたくさんあります.netty-codec
netty-codec-http
netty-codec-http2
netty-codec-memcache
netty-codec-redis
netty-codec-socks
netty-codec-stomp
netty-codec-mqtt
netty-codec-haproxy
netty-codec-dns
全部で10個のcodecパッケージがあり、そのうちnetty-codecが最も基礎的な1つであり、他の9個は異なるプロトコルパッケージに対する拡張と適合であり、nettyがよく使われるプロトコルフォーマットと流行しているプロトコルフォーマットをサポートしていることがわかり、非常に強力である.codecの内容が非常に多いため、説明するのも容易ではありません.本稿ではnetty-codecを例に、その中で最も基本的で最も一般的な符号化デコーダを説明します.
codecの使用に注意すべき問題
nettyは便利なcodec符号化デコーダを提供していますが、前の記事で述べたように、Frame detectionと一緒に使用する必要があるcodecもあります.まずFrame detectionを使用してByteBufを実際のデータを表すByteBufに分割し、nettyに内蔵されたcodecまたはカスタムcodecに渡して処理すると、効果的です.
Netty内蔵の基本codec
Nettyの基本的なcodecにはbase 64、bytes、compression、json、marshalling、protobuf、serialization、string、xmlのいくつかがあります.
以下、一つ一つ説明します.
base64
このcodecは、ByteBufとbase 64以降のByteBufとの間の変換を担当する.いずれもByteBufからByteBufまでですが、その内容が変わりました.
Base 64 EncoderとBase 64 Decoderの2つの重要なクラスがあります.Base 64 DecoderはMessageToMessageDecoderであるため、DelimiterBasedFrameDecoderを使用して事前に処理する必要があります.一般的な例は次のとおりです. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(80, Delimiters.nulDelimiter()));
pipeline.addLast("base64Decoder", new Base64Decoder());
// Encoder
pipeline.addLast("base64Encoder", new Base64Encoder());
bytes
bytesはbytes配列とByteBufの間を変換し、同様にdecodeの前にFrameDecoderを使用する必要があります.通常の使用方法は以下の通りです. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("bytesDecoder",
new ByteArrayDecoder());
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("bytesEncoder", new ByteArrayEncoder());
compression
compressionというパッケージの内容は比較的豊富で、主にデータの圧縮と解凍サービスです.サポートされるアルゴリズムは次のとおりです.brotli
Bzip2
FastLZ
JdkZlib
Lz4
Lzf
Snappy
Zlib
Zstandard
compressionは、大きなデータ量の伝送に特に役立ち、圧縮により伝送されるデータ量を節約し、伝送速度を向上させることができる.
しかし、圧縮は特定のアルゴリズムを用いて計算されるので、高いCPUの操作であり、ネットワーク速度とCPU性能を両立させ、バランスをとる必要があります.
json
jsonこのパッケージにはJsonObjectDecoderクラスが1つしかありません.主にByteストリームのJSONオブジェクトまたは配列をJSONオブジェクトと配列に変換します.
JsonObjectDecoderは直接ByteToMesageDecoderのサブクラスであるため、FrameDecoderは不要であり、カッコの一致に基づいてByte配列の開始位置を判断し、どのByteデータが同じJsonオブジェクトまたは配列に属しているかを区別する.
JSONを使ってデータを転送したいなら、このクラスはとても役に立ちます.
marshalling
MarshallingのフルネームはJBoss Marshallingと呼ばれ、JBoss出品のオブジェクトをシーケンス化する方法ですが、JBoss Marshallingの最新APIは2011-04-27で、すでに10年も更新されていませんが、廃棄されているのではないでしょうか.
だからここではこのシーケンス化の内容を詳しく紹介しないで、興味のある仲間は自分で探求することができます.
protobuf
protobufはよく知られているはずですが、google出品の情報交換フォーマットであり、シーケンス化された方法と見なすことができます.これは言語中立、プラットフォーム中立、拡張性のある構造化データシーケンス化メカニズムであり、XMLと似ていますが、XMLよりも小さく、より速く、より簡単です.
Nettyのprotobufのサポートは、protobufのmessageおよびMessageLiteオブジェクトをByteBufに変換できることです.
protobufの2つのエンコーダもmessageからmessageへの直接的な変換なのでframe detectionも使用する必要があります.もちろん、LengthFieldPrependerやLengthFieldBasedFrameDecoderのような他のframe detectionも使用できます. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("protobufDecoder",
new ProtobufDecoder(MyMessage.getDefaultInstance()));
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("protobufEncoder", new ProtobufEncoder());
LengthFieldPrependerでは、フィールドの前に長さフィールドが自動的に追加されます. :
+----------------+
| "HELLO, WORLD" |
+----------------+
:
+--------+----------------+
+ 0x000C | "HELLO, WORLD" |
+--------+----------------+
もちろんnettyはprotobufのために2つの専門的なframe detectionを用意しています.彼らはProtobufVarint 32 FrameDecoderとProtobufVarint 32 LengthFieldPrependerです.この2つのクラスを説明する前に、protobufのBase 128 Varintsについて理解する必要があります.
ヴァリエンスって何?つまり、整数をシーケンス化する場合、占有する空間の大きさは異なり、小さい整数が占有する空間は小さく、大きい整数が占有する空間は大きく、このように具体的な長さを固定する必要がなく、データの長さを減らすことができるが、解析の複雑さをもたらす.
では、このデータにはいったい何byteが必要なのか、どうやって知るのでしょうか.protobufでは、各byteの最上位は1つの判定ビットであり、このビットが1に置かれている場合は、後のbyteとそのbyteが一緒であることを示し、同じ数を示し、このビットが0に置かれている場合は、後のbyteとそのbyteが関係していないことを示し、このbyteにデータが終了する.
例えば、1つのbyteは8ビットであり、整数1を表す場合、以下のbyteで表すことができる.0000 0001
1つのbyteに整数が入れられない場合は、次のデータが300を表すように、複数のbyteを使用して接続操作を行う必要があります.1010 1100 0000 0010
どうして300ですか.まず最初のbyteを見て、その首位は1で、後ろにもう一つのbyteがあることを示します.2番目のbyteを見ると、トップは0で、これで終わりです.私たちは判断を外して、次の数字になります.010 1100 000 0010
この場合、データの値を計算することはできません.protobufではbyteの桁数が逆なので、上の2つのbyteを位置を交換する必要があります.000 0010 010 1100
つまり、10 010 1100
=256 + 32 + 8 + 4 = 300
protobufでは一般にVarintがフィールドの長さビットとして使用されるため、nettyはProtobufVarint 32 LengthFieldPrependerとProtobufVarint 32 FrameDecoderがByteBufを変換することを提供する.
たとえば、ByteBufにvarintのlengthを追加します. BEFORE ENCODE (300 bytes) AFTER ENCODE (302 bytes)
+---------------+ +--------+---------------+
| Protobuf Data |-------------->| Length | Protobuf Data |
| (300 bytes) | | 0xAC02 | (300 bytes) |
+---------------+ +--------+---------------+
復号時にvarintのlengthフィールドを削除します. BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)
+--------+---------------+ +---------------+
| Length | Protobuf Data |----->| Protobuf Data |
| 0xAC02 | (300 bytes) | | (300 bytes) |
+--------+---------------+ +---------------+
serialization
シーケンス化とは,オブジェクトをバイナリデータに変換することであり,実際にはすべてのcodecがシーケンス化できる.オブジェクトとbyte間の変換方法を提供します.
Nettyは、ObjectDecoderとObjectEncoderの2つのオブジェクトの変換方法も提供します.
なお、この2つのオブジェクトとJDKが持つObjectInputStreamとObjectOutputStreamは互換性がなく、互換性がある場合はCompactObjectInputStream、CompactObjectOutputStream、CompatibleObjectEncoderを使用できます.
string
Stringは私たちが最もよく使うオブジェクトで、nettyはstringにStringDecoderとStringEncoderを提供しています.
同様に、この2つのクラスを使用する前に、メッセージを変換する必要があります.通常はLineBasedFrameDecoderを使用して行ごとに変換します. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
xml
xmlも非常に一般的なフォーマットですが、体積が大きくなり、今では少ないはずです.NettyはXmlFrameDecoderを提供して解析を行う.
xmlには独自の開始記号と終了記号があるので、frame detectionをする必要はありません. +-----+-----+-----------+
| |
+-----+-----+-----------+
:
+-----------------+
| |
+-----------------+
+-----+-----+-----------+-----+----------------------------------+
| | content |
+-----+-----+-----------+-----+----------------------------------+
:
+-----------------+-------------------------------------+
| | content |
+-----------------+-------------------------------------+
すべて可能です.
まとめ
Nettyは多くの優秀なcodecを提供して各種の応用プロトコルに適して、みんなは多く使って、異なるプロトコルの違いを探すことができます.
この文書はhttp://www.flydean.com/16-netty-buildin-codec-common/に収録されています.
最も通俗的な解読、最も深い乾物、最も簡潔なチュートリアル、多くのあなたが知らない小さなテクニックなどを発見します!
私の公衆番号に注目することを歓迎します:“プログラムのあれらの事”、技術を理解して、更にあなたを理解します!
nettyのパッケージを導入すると、nettyにはnetty-codecで始まるartifactIdがたくさんあることがわかります.統計すると、こんなにたくさんあります.
netty-codec
netty-codec-http
netty-codec-http2
netty-codec-memcache
netty-codec-redis
netty-codec-socks
netty-codec-stomp
netty-codec-mqtt
netty-codec-haproxy
netty-codec-dns
全部で10個のcodecパッケージがあり、そのうちnetty-codecが最も基礎的な1つであり、他の9個は異なるプロトコルパッケージに対する拡張と適合であり、nettyがよく使われるプロトコルフォーマットと流行しているプロトコルフォーマットをサポートしていることがわかり、非常に強力である.codecの内容が非常に多いため、説明するのも容易ではありません.本稿ではnetty-codecを例に、その中で最も基本的で最も一般的な符号化デコーダを説明します.
codecの使用に注意すべき問題
nettyは便利なcodec符号化デコーダを提供していますが、前の記事で述べたように、Frame detectionと一緒に使用する必要があるcodecもあります.まずFrame detectionを使用してByteBufを実際のデータを表すByteBufに分割し、nettyに内蔵されたcodecまたはカスタムcodecに渡して処理すると、効果的です.
Netty内蔵の基本codec
Nettyの基本的なcodecにはbase 64、bytes、compression、json、marshalling、protobuf、serialization、string、xmlのいくつかがあります.
以下、一つ一つ説明します.
base64
このcodecは、ByteBufとbase 64以降のByteBufとの間の変換を担当する.いずれもByteBufからByteBufまでですが、その内容が変わりました.
Base 64 EncoderとBase 64 Decoderの2つの重要なクラスがあります.Base 64 DecoderはMessageToMessageDecoderであるため、DelimiterBasedFrameDecoderを使用して事前に処理する必要があります.一般的な例は次のとおりです. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(80, Delimiters.nulDelimiter()));
pipeline.addLast("base64Decoder", new Base64Decoder());
// Encoder
pipeline.addLast("base64Encoder", new Base64Encoder());
bytes
bytesはbytes配列とByteBufの間を変換し、同様にdecodeの前にFrameDecoderを使用する必要があります.通常の使用方法は以下の通りです. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("bytesDecoder",
new ByteArrayDecoder());
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("bytesEncoder", new ByteArrayEncoder());
compression
compressionというパッケージの内容は比較的豊富で、主にデータの圧縮と解凍サービスです.サポートされるアルゴリズムは次のとおりです.brotli
Bzip2
FastLZ
JdkZlib
Lz4
Lzf
Snappy
Zlib
Zstandard
compressionは、大きなデータ量の伝送に特に役立ち、圧縮により伝送されるデータ量を節約し、伝送速度を向上させることができる.
しかし、圧縮は特定のアルゴリズムを用いて計算されるので、高いCPUの操作であり、ネットワーク速度とCPU性能を両立させ、バランスをとる必要があります.
json
jsonこのパッケージにはJsonObjectDecoderクラスが1つしかありません.主にByteストリームのJSONオブジェクトまたは配列をJSONオブジェクトと配列に変換します.
JsonObjectDecoderは直接ByteToMesageDecoderのサブクラスであるため、FrameDecoderは不要であり、カッコの一致に基づいてByte配列の開始位置を判断し、どのByteデータが同じJsonオブジェクトまたは配列に属しているかを区別する.
JSONを使ってデータを転送したいなら、このクラスはとても役に立ちます.
marshalling
MarshallingのフルネームはJBoss Marshallingと呼ばれ、JBoss出品のオブジェクトをシーケンス化する方法ですが、JBoss Marshallingの最新APIは2011-04-27で、すでに10年も更新されていませんが、廃棄されているのではないでしょうか.
だからここではこのシーケンス化の内容を詳しく紹介しないで、興味のある仲間は自分で探求することができます.
protobuf
protobufはよく知られているはずですが、google出品の情報交換フォーマットであり、シーケンス化された方法と見なすことができます.これは言語中立、プラットフォーム中立、拡張性のある構造化データシーケンス化メカニズムであり、XMLと似ていますが、XMLよりも小さく、より速く、より簡単です.
Nettyのprotobufのサポートは、protobufのmessageおよびMessageLiteオブジェクトをByteBufに変換できることです.
protobufの2つのエンコーダもmessageからmessageへの直接的な変換なのでframe detectionも使用する必要があります.もちろん、LengthFieldPrependerやLengthFieldBasedFrameDecoderのような他のframe detectionも使用できます. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("protobufDecoder",
new ProtobufDecoder(MyMessage.getDefaultInstance()));
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("protobufEncoder", new ProtobufEncoder());
LengthFieldPrependerでは、フィールドの前に長さフィールドが自動的に追加されます. :
+----------------+
| "HELLO, WORLD" |
+----------------+
:
+--------+----------------+
+ 0x000C | "HELLO, WORLD" |
+--------+----------------+
もちろんnettyはprotobufのために2つの専門的なframe detectionを用意しています.彼らはProtobufVarint 32 FrameDecoderとProtobufVarint 32 LengthFieldPrependerです.この2つのクラスを説明する前に、protobufのBase 128 Varintsについて理解する必要があります.
ヴァリエンスって何?つまり、整数をシーケンス化する場合、占有する空間の大きさは異なり、小さい整数が占有する空間は小さく、大きい整数が占有する空間は大きく、このように具体的な長さを固定する必要がなく、データの長さを減らすことができるが、解析の複雑さをもたらす.
では、このデータにはいったい何byteが必要なのか、どうやって知るのでしょうか.protobufでは、各byteの最上位は1つの判定ビットであり、このビットが1に置かれている場合は、後のbyteとそのbyteが一緒であることを示し、同じ数を示し、このビットが0に置かれている場合は、後のbyteとそのbyteが関係していないことを示し、このbyteにデータが終了する.
例えば、1つのbyteは8ビットであり、整数1を表す場合、以下のbyteで表すことができる.0000 0001
1つのbyteに整数が入れられない場合は、次のデータが300を表すように、複数のbyteを使用して接続操作を行う必要があります.1010 1100 0000 0010
どうして300ですか.まず最初のbyteを見て、その首位は1で、後ろにもう一つのbyteがあることを示します.2番目のbyteを見ると、トップは0で、これで終わりです.私たちは判断を外して、次の数字になります.010 1100 000 0010
この場合、データの値を計算することはできません.protobufではbyteの桁数が逆なので、上の2つのbyteを位置を交換する必要があります.000 0010 010 1100
つまり、10 010 1100
=256 + 32 + 8 + 4 = 300
protobufでは一般にVarintがフィールドの長さビットとして使用されるため、nettyはProtobufVarint 32 LengthFieldPrependerとProtobufVarint 32 FrameDecoderがByteBufを変換することを提供する.
たとえば、ByteBufにvarintのlengthを追加します. BEFORE ENCODE (300 bytes) AFTER ENCODE (302 bytes)
+---------------+ +--------+---------------+
| Protobuf Data |-------------->| Length | Protobuf Data |
| (300 bytes) | | 0xAC02 | (300 bytes) |
+---------------+ +--------+---------------+
復号時にvarintのlengthフィールドを削除します. BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)
+--------+---------------+ +---------------+
| Length | Protobuf Data |----->| Protobuf Data |
| 0xAC02 | (300 bytes) | | (300 bytes) |
+--------+---------------+ +---------------+
serialization
シーケンス化とは,オブジェクトをバイナリデータに変換することであり,実際にはすべてのcodecがシーケンス化できる.オブジェクトとbyte間の変換方法を提供します.
Nettyは、ObjectDecoderとObjectEncoderの2つのオブジェクトの変換方法も提供します.
なお、この2つのオブジェクトとJDKが持つObjectInputStreamとObjectOutputStreamは互換性がなく、互換性がある場合はCompactObjectInputStream、CompactObjectOutputStream、CompatibleObjectEncoderを使用できます.
string
Stringは私たちが最もよく使うオブジェクトで、nettyはstringにStringDecoderとStringEncoderを提供しています.
同様に、この2つのクラスを使用する前に、メッセージを変換する必要があります.通常はLineBasedFrameDecoderを使用して行ごとに変換します. ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
xml
xmlも非常に一般的なフォーマットですが、体積が大きくなり、今では少ないはずです.NettyはXmlFrameDecoderを提供して解析を行う.
xmlには独自の開始記号と終了記号があるので、frame detectionをする必要はありません. +-----+-----+-----------+
| |
+-----+-----+-----------+
:
+-----------------+
| |
+-----------------+
+-----+-----+-----------+-----+----------------------------------+
| | content |
+-----+-----+-----------+-----+----------------------------------+
:
+-----------------+-------------------------------------+
| | content |
+-----------------+-------------------------------------+
すべて可能です.
まとめ
Nettyは多くの優秀なcodecを提供して各種の応用プロトコルに適して、みんなは多く使って、異なるプロトコルの違いを探すことができます.
この文書はhttp://www.flydean.com/16-netty-buildin-codec-common/に収録されています.
最も通俗的な解読、最も深い乾物、最も簡潔なチュートリアル、多くのあなたが知らない小さなテクニックなどを発見します!
私の公衆番号に注目することを歓迎します:“プログラムのあれらの事”、技術を理解して、更にあなたを理解します!
Nettyの基本的なcodecにはbase 64、bytes、compression、json、marshalling、protobuf、serialization、string、xmlのいくつかがあります.
以下、一つ一つ説明します.
base64
このcodecは、ByteBufとbase 64以降のByteBufとの間の変換を担当する.いずれもByteBufからByteBufまでですが、その内容が変わりました.
Base 64 EncoderとBase 64 Decoderの2つの重要なクラスがあります.Base 64 DecoderはMessageToMessageDecoderであるため、DelimiterBasedFrameDecoderを使用して事前に処理する必要があります.一般的な例は次のとおりです.
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(80, Delimiters.nulDelimiter()));
pipeline.addLast("base64Decoder", new Base64Decoder());
// Encoder
pipeline.addLast("base64Encoder", new Base64Encoder());
bytes
bytesはbytes配列とByteBufの間を変換し、同様にdecodeの前にFrameDecoderを使用する必要があります.通常の使用方法は以下の通りです.
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("bytesDecoder",
new ByteArrayDecoder());
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("bytesEncoder", new ByteArrayEncoder());
compression
compressionというパッケージの内容は比較的豊富で、主にデータの圧縮と解凍サービスです.サポートされるアルゴリズムは次のとおりです.
brotli
Bzip2
FastLZ
JdkZlib
Lz4
Lzf
Snappy
Zlib
Zstandard
compressionは、大きなデータ量の伝送に特に役立ち、圧縮により伝送されるデータ量を節約し、伝送速度を向上させることができる.
しかし、圧縮は特定のアルゴリズムを用いて計算されるので、高いCPUの操作であり、ネットワーク速度とCPU性能を両立させ、バランスをとる必要があります.
json
jsonこのパッケージにはJsonObjectDecoderクラスが1つしかありません.主にByteストリームのJSONオブジェクトまたは配列をJSONオブジェクトと配列に変換します.
JsonObjectDecoderは直接ByteToMesageDecoderのサブクラスであるため、FrameDecoderは不要であり、カッコの一致に基づいてByte配列の開始位置を判断し、どのByteデータが同じJsonオブジェクトまたは配列に属しているかを区別する.
JSONを使ってデータを転送したいなら、このクラスはとても役に立ちます.
marshalling
MarshallingのフルネームはJBoss Marshallingと呼ばれ、JBoss出品のオブジェクトをシーケンス化する方法ですが、JBoss Marshallingの最新APIは2011-04-27で、すでに10年も更新されていませんが、廃棄されているのではないでしょうか.
だからここではこのシーケンス化の内容を詳しく紹介しないで、興味のある仲間は自分で探求することができます.
protobuf
protobufはよく知られているはずですが、google出品の情報交換フォーマットであり、シーケンス化された方法と見なすことができます.これは言語中立、プラットフォーム中立、拡張性のある構造化データシーケンス化メカニズムであり、XMLと似ていますが、XMLよりも小さく、より速く、より簡単です.
Nettyのprotobufのサポートは、protobufのmessageおよびMessageLiteオブジェクトをByteBufに変換できることです.
protobufの2つのエンコーダもmessageからmessageへの直接的な変換なのでframe detectionも使用する必要があります.もちろん、LengthFieldPrependerやLengthFieldBasedFrameDecoderのような他のframe detectionも使用できます.
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder",
new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
pipeline.addLast("protobufDecoder",
new ProtobufDecoder(MyMessage.getDefaultInstance()));
// Encoder
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("protobufEncoder", new ProtobufEncoder());
LengthFieldPrependerでは、フィールドの前に長さフィールドが自動的に追加されます.
:
+----------------+
| "HELLO, WORLD" |
+----------------+
:
+--------+----------------+
+ 0x000C | "HELLO, WORLD" |
+--------+----------------+
もちろんnettyはprotobufのために2つの専門的なframe detectionを用意しています.彼らはProtobufVarint 32 FrameDecoderとProtobufVarint 32 LengthFieldPrependerです.この2つのクラスを説明する前に、protobufのBase 128 Varintsについて理解する必要があります.
ヴァリエンスって何?つまり、整数をシーケンス化する場合、占有する空間の大きさは異なり、小さい整数が占有する空間は小さく、大きい整数が占有する空間は大きく、このように具体的な長さを固定する必要がなく、データの長さを減らすことができるが、解析の複雑さをもたらす.
では、このデータにはいったい何byteが必要なのか、どうやって知るのでしょうか.protobufでは、各byteの最上位は1つの判定ビットであり、このビットが1に置かれている場合は、後のbyteとそのbyteが一緒であることを示し、同じ数を示し、このビットが0に置かれている場合は、後のbyteとそのbyteが関係していないことを示し、このbyteにデータが終了する.
例えば、1つのbyteは8ビットであり、整数1を表す場合、以下のbyteで表すことができる.
0000 0001
1つのbyteに整数が入れられない場合は、次のデータが300を表すように、複数のbyteを使用して接続操作を行う必要があります.
1010 1100 0000 0010
どうして300ですか.まず最初のbyteを見て、その首位は1で、後ろにもう一つのbyteがあることを示します.2番目のbyteを見ると、トップは0で、これで終わりです.私たちは判断を外して、次の数字になります.
010 1100 000 0010
この場合、データの値を計算することはできません.protobufではbyteの桁数が逆なので、上の2つのbyteを位置を交換する必要があります.
000 0010 010 1100
つまり、
10 010 1100
=256 + 32 + 8 + 4 = 300
protobufでは一般にVarintがフィールドの長さビットとして使用されるため、nettyはProtobufVarint 32 LengthFieldPrependerとProtobufVarint 32 FrameDecoderがByteBufを変換することを提供する.
たとえば、ByteBufにvarintのlengthを追加します.
BEFORE ENCODE (300 bytes) AFTER ENCODE (302 bytes)
+---------------+ +--------+---------------+
| Protobuf Data |-------------->| Length | Protobuf Data |
| (300 bytes) | | 0xAC02 | (300 bytes) |
+---------------+ +--------+---------------+
復号時にvarintのlengthフィールドを削除します.
BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)
+--------+---------------+ +---------------+
| Length | Protobuf Data |----->| Protobuf Data |
| 0xAC02 | (300 bytes) | | (300 bytes) |
+--------+---------------+ +---------------+
serialization
シーケンス化とは,オブジェクトをバイナリデータに変換することであり,実際にはすべてのcodecがシーケンス化できる.オブジェクトとbyte間の変換方法を提供します.
Nettyは、ObjectDecoderとObjectEncoderの2つのオブジェクトの変換方法も提供します.
なお、この2つのオブジェクトとJDKが持つObjectInputStreamとObjectOutputStreamは互換性がなく、互換性がある場合はCompactObjectInputStream、CompactObjectOutputStream、CompatibleObjectEncoderを使用できます.
string
Stringは私たちが最もよく使うオブジェクトで、nettyはstringにStringDecoderとStringEncoderを提供しています.
同様に、この2つのクラスを使用する前に、メッセージを変換する必要があります.通常はLineBasedFrameDecoderを使用して行ごとに変換します.
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
xml
xmlも非常に一般的なフォーマットですが、体積が大きくなり、今では少ないはずです.NettyはXmlFrameDecoderを提供して解析を行う.
xmlには独自の開始記号と終了記号があるので、frame detectionをする必要はありません.
+-----+-----+-----------+
| |
+-----+-----+-----------+
:
+-----------------+
| |
+-----------------+
+-----+-----+-----------+-----+----------------------------------+
| | content |
+-----+-----+-----------+-----+----------------------------------+
:
+-----------------+-------------------------------------+
| | content |
+-----------------+-------------------------------------+
すべて可能です.