質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Network+

Network+とは、IT業界団体CompTIA認定のネットワーク技術に関する知識を証明する資格です。ネットワーク技術者として、実務で必要なネットワークセキュリティ・ネットワークアーキテクチャなどの知識を取得している証明となります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2375閲覧

Pythonでのパケットのデコード(?)について

退会済みユーザー

退会済みユーザー

総合スコア0

Network+

Network+とは、IT業界団体CompTIA認定のネットワーク技術に関する知識を証明する資格です。ネットワーク技術者として、実務で必要なネットワークセキュリティ・ネットワークアーキテクチャなどの知識を取得している証明となります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2017/03/14 13:13

編集2017/03/14 14:03

###pythonでのパケットのデコード
現在、独学でネットワークプログラミングについて勉強している者です。その途中で一つわからな
いことが出たので質問させていただきます。

今、websocketサーバーのソースコードをgithubから見つけ読んでいたのですが、
クライアントから到着したパケットを解析するメソッドにおいて

def _parseMessage(self, byte): self.fin = byte & 0x80 self.opcode = byte & 0x0F rsv = byte & 0x70

(URLです。)
https://github.com/dpallot/simple-websocket-server/blob/master/SimpleWebSocketServer/SimpleWebSocketServer.py#L415

という記述を見つけました。self.finはメッセージの最後の断片であるかどうかを表すものであり、
self.opcodeはペイロードの解釈の定義、rsvは予約済みビットであることはRFCなどから理解で
きるのですが、なぜbyte & 0x80というふうにビット演算子を使用しているのかその意図がよくわ
かりません。
例えばself.finであれば

self.fin = byte & 0x80 #これ↑は 128 = 129 & 128 # byteには129が渡されていました。また,0x80は128でありました。

というふうになるのですが、なぜこうする必要があるのか。

下手な説明で申し訳ありませんが、よろしくおねがいします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

_parseMessage に渡ってくる1byteのデータの最初のbitがfinを表すためです。
最初のbit, つまり1byteの最上位ビットを調べたいので、 0x80 = 2進数表現だと 0b10000000 でマスクしています。

RFC 6455 The WebSocket Protocol - 5.2. Base Framing Protocol から引用します

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+ FIN: 1 bit Indicates that this is the final fragment in a message. The first fragment MAY also be the final fragment.

この図から、最初の1byte = 8bitの構成要素の内、0x80(=0b10000000)でマスクするとFIN, 0x0F(=0b00001111)でマスクするとopcodeが取得出来ることが分かります。

ソースコード中のコードをこれに従って読み解くと以下のようになります。

Python

1 self.fin = byte & 0x80 # 0b10000000でマスク 2 self.opcode = byte & 0x0F # 0b00001111でマスク 3 rsv = byte & 0x70 # 0b01110000 でマスク

通信データのパケットでは、1byteの中に複数の情報を詰め込んでいるため、1byte未満のbit単位で値を解釈する必要があるため、このようにマスク処理をして、興味のあるbitの状態を確認します。このようなデータを読み解く際に、1byteのデータをそのまま10進数で解釈しないほうがよいです。

投稿2017/03/14 14:16

shimizukawa

総合スコア1847

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shimizukawa

2017/03/14 14:20 編集

余談ですが、Pythonのbin関数を使うと、bitの状態を視覚的に見易くなるのでデバッグ時に重宝します。 >>> print(bin(129)) 0b10000001 慣れてくると16進数表現でも十分に理解できるようになってきますよ。 >>> print(hex(129)) 0x81
退会済みユーザー

退会済みユーザー

2017/03/14 14:41 編集

早速の回答ありがとうございます。疑問が解決し、また、自分のパケットの図の解釈が間違っていたこともわかりました。これで先に進めます。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問