2012年3月31日土曜日

websocketについて再度やってみる。その2

データの送受信まわりの動作について調べてみました。
サンプルはあるもののどうも英語の仕様を読み解くのは苦手ですね。
今回もhybi-00とRFC6455の両方について書いておきます。

まずは単純なhybi-00の方。
こちらは単にUTF-8のバイトデータの先頭と最終に0x00と0xffをつければOK
たとえばHelloだとバイトデータが
0x48 0x65 0x6c 0x6c 0x6fになるので
0x00 0x48 0x65 0x6c 0x6c 0x6f 0xff
にして、送信すればOKです。受け取ったデータも同じ。

続いてちょっとややこしいRFC6455の方。
こちらでは、テキストデータ、バイナリデータのほかに、pingフラグ、pongフラグ、切断命令等々あります。またXORによるマスク指定もあります。

まず一番単純なデータから
送信データはHello
0x48 0x65 0x6c 0x6c 0x6f
ヘッダデータが必要なのでそのデータを追加して
0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f
このようになります。
先頭の1バイトはビットに変換すると、
1000 0001になります。
先頭1ビットは今回のパケットで命令がおわるかどうかの指定です。1がはいっている場合はおわる。0がはいっている場合は、あとから別途命令が送られてくる印になります。
次の3ビットは0に予約されています。
後ろの4ビットはデータが何であるかの指定です。
1:テキスト 2:バイナリ 3-7は将来に予約 8はコネクションを閉じる 9はping Aはpong、B-Fは将来に予約となっています。
よって0x81は今回の通信で終了するテキストデータ
0x01はあとで別のデータが追記されるテキストデータ
0x82は今回の通信で終了するバイナリデータといった具合になります。
次の1バイトはマスクフラグとメッセージの長さになります。
例では0x05になっています。ビットに変換すると
0000 0101となります。
先頭の1ビットが0になっているので、今回はマスクはなし。のこりのビットデータによるとデータが5になるので、後ろの5バイトがメッセージデータということになります。
後ろの5バイトの0x48 0x65 0x6c 0x6c 0x6fがUTFコードでHelloという文字になりますので、このデータは[今回の転送のみで完了するデータのマスクなし、5バイトのデータHello]
ということになります。

続いてあとで別のデータが追記される場合のサンプル
0x01 0x03 0x48 0x65 0x6c
0x81 0x02 0x6c 0x6f
こんな感じになります。
まず始めのデータ

0x01 0x03 0x48 0x65 0x6c
1バイト目が0000 0001になっているので、今回のメッセージで完了しないデータかつ、テキストデータという指定になります。
2バイト目、0000 0011になっているので、マスクはなし。長さは3バイト
んで、うしろの3バイトをみるとHelになっています。
2つ目のデータ
0x81 0x02 0x6c 0x6f
1バイト目が1000 0001になっているので、今回のメッセージで完了する。かつテキスト
2バイト目が0000 0010になっているので、マスクフラグはなし、長さは2バイト
んで、うしろの2バイトをみるとloになっています。
前のデータとあわせるとHelloというデータになります。

続いてマスクがある場合の動作
例Hello
0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
こんなデータになります。
まず先頭1バイトですが、1000 0001となっているので、今回でおわりのテキストデータとなります。
次に2バイト目 1000 0101となり、マスクビットが設定されている(先頭の1ビット目)でサイズは5バイトとなります。
そこから続く4バイトはマスク用の値となります。
0x37 0xfa 0x21 0x3dが対象です。
最後の5バイトがHelloを表しています。
0x7f 0x9f 0x4d 0x51 0x58
で、復号の仕方なわけですが、XORでマスク用の値と掛け合わせてやればOKです。
0x7fは0x37と、0x9fは0xfaと・・・という順番で組み合わせていき、4つ目までおわったらまた始めに戻ります。なので5文字目の0x58は0x37と掛け合わせます。
0x37とx07fはビットにすると
0011 0111 (0x37)
0111 1111 (0x7f)
xorにかけてやると
0100 1000 (0x48)になり。これはHを表します。

どうように0xfaと0x9fでは
1111 1010 (0xfa)
1001 1111 (0x9f)

0110 0101 (0x65)になりe

0010 0001 (0x21)
0100 1101 (0x4d)
0110 1100 (0x6c) → l

0011 1101 (0x3d)
0101 0001 (0x51)
0110 1100 (0x6c) → l

0011 0111 (0x37)
0101 1000 (0x58)
0110 1111 (0x6f) → o
というわけで、Helloとなるわけです。

以上でwebsocketで送信されてくるデータをUTF-8の文字に変えたり元に戻したりできるようになりました。

0 件のコメント:

コメントを投稿