Erlangバイナリモードマッチング
3881 ワード
Erlangのモードマッチングはバイナリデータの処理に適していると言える.直感的であるのみならず、想像以上に簡単である.C++では,バイナリデータの処理はまずバッファを管理する.その後、バイト単位で操作し、処理するデータがバイト単位で整列していない場合は、シフトなどの操作が必要です.操作過程は複雑で分かりにくいが、注釈がなければ、このコードを維持する人にとっては悪夢だ.たとえば、RGBの色値シーケンスが保存されているバイナリ列を操作します.C++では、次のようにします.
まず、RGB構造を定義し、RGBデータストリームがpixelsが指すアドレスに保存され、対応するRGB値がループ解析され、配列に保存されると仮定します.同等の機能を実現するErlangは、次のように1行で完了します.
簡単なのではないでしょうか.また、上記の例では、RGBの値はちょうど1バイトなので、C++での処理は比較的簡単です.もっと複雑な例を見てみましょう.この例はErlangの公式ドキュメントで紹介されています.ここをスタンプすることができます.これはIPパケットヘッダを解析する例であり(IPパケットヘッダスタンプここを理解していない場合)、Erlangではこのようにする必要がある.
このコードを見ると、何をするのか、いろいろな値の位置、占有空間の大きさ、代表的な意味が一目瞭然で、見ていると本当に気持ちがいいです.このような処理方法を初めて見たとき、バイナリデータの処理がこんなに簡単で直感的だったことに興奮しました.わかりやすいですが、ここで簡単にご紹介します.まずsize関数でIPパケット全体の長さを取得します.次に、パケット全体をバイナリモードマッチングします.IPパケットヘッダのフォーマットによると、0-3ビットはプロトコルバージョン番号であり、IPV 4にとってここは4であるはずなので、モードマッチング時に直接<<4:4、Rest/binary>>でバージョン番号にマッチングできます.上記の例では4を1つのマクロとして定義する.次の4-7ビットはIPヘッダの長さです.後の私は詳しく紹介しません.具体的なIPヘッダはここを参照してください.私がここでこの例を挙げるのは、本当にErlangでIPパケットを解析するためではなく、Erlangがバイナリを解析する利点を説明するためだけです.
最後に、私の今のゲームサーバーのパッケージの解析をあげます.パケットヘッダは、16ビットのパケット長と16ビットのメッセージコードからなり、合計4バイトである.解析の方法は次のとおりです.
ここで、Dataは元のパケットであり、DataLenはパケット長であり、Commandはメッセージコードであり、RDataはパケット体である.もちろん、実際のプロジェクトでは、粘着パケット、半パケット、および対応するエラー処理部分も考慮され、ここではバイナリモードマッチングのみが提供される.
struct RGB
{
char R;
char G;
char B;
};
vector<RGB> rgbVector;
for(int i = 0; i < pixelsLen; i = i + 3)
{
RGB rgb;
rgb.R = pixels[i];
rgb.G = pixels[i + 1];
rgb.B = pixels[i + 2];
rgbVector.push_back(rgb);
}
まず、RGB構造を定義し、RGBデータストリームがpixelsが指すアドレスに保存され、対応するRGB値がループ解析され、配列に保存されると仮定します.同等の機能を実現するErlangは、次のように1行で完了します.
Pixels = <<213,45,132,64,76,0,0,234,32,15>>.
RGB = [ {R,G,B} || <<R:8,G:8,B:8>> <= Pixels ].
簡単なのではないでしょうか.また、上記の例では、RGBの値はちょうど1バイトなので、C++での処理は比較的簡単です.もっと複雑な例を見てみましょう.この例はErlangの公式ドキュメントで紹介されています.ここをスタンプすることができます.これはIPパケットヘッダを解析する例であり(IPパケットヘッダスタンプここを理解していない場合)、Erlangではこのようにする必要がある.
-define(IP_VERSION, 4).
-define(IP_MIN_HDR_LEN, 5).
DgramSize = size(Dgram),
case Dgram of
<<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
ID:16, Flgs:3, FragOff:13,
TTL:8, Proto:8, HdrChkSum:16,
SrcIP:32,
DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
<<Opts:OptsLen/binary,Data/binary>> = RestDgram,
...
end.
このコードを見ると、何をするのか、いろいろな値の位置、占有空間の大きさ、代表的な意味が一目瞭然で、見ていると本当に気持ちがいいです.このような処理方法を初めて見たとき、バイナリデータの処理がこんなに簡単で直感的だったことに興奮しました.わかりやすいですが、ここで簡単にご紹介します.まずsize関数でIPパケット全体の長さを取得します.次に、パケット全体をバイナリモードマッチングします.IPパケットヘッダのフォーマットによると、0-3ビットはプロトコルバージョン番号であり、IPV 4にとってここは4であるはずなので、モードマッチング時に直接<<4:4、Rest/binary>>でバージョン番号にマッチングできます.上記の例では4を1つのマクロとして定義する.次の4-7ビットはIPヘッダの長さです.後の私は詳しく紹介しません.具体的なIPヘッダはここを参照してください.私がここでこの例を挙げるのは、本当にErlangでIPパケットを解析するためではなく、Erlangがバイナリを解析する利点を説明するためだけです.
最後に、私の今のゲームサーバーのパッケージの解析をあげます.パケットヘッダは、16ビットのパケット長と16ビットのメッセージコードからなり、合計4バイトである.解析の方法は次のとおりです.
<<DataLen:16,Command:16,RData/binary>> = Data
ここで、Dataは元のパケットであり、DataLenはパケット長であり、Commandはメッセージコードであり、RDataはパケット体である.もちろん、実際のプロジェクトでは、粘着パケット、半パケット、および対応するエラー処理部分も考慮され、ここではバイナリモードマッチングのみが提供される.