web-dev-qa-db-ja.com

Pythonを使用してソケット経由でバイナリデータを送信する

SPDYプロトコル を介した基本的なリクエストのスクリプトを作成しようとしています。プロトコルは、送信するフレームを非常に特定の長さとバイト順のバイナリデータで構成されるものとして定義します。

ソケット(HTTP)を介して文字列を送信する小さなプログラムを作成したことがあります。たとえば、SPDYコントロールフレームヘッダーを実装するにはどうすればよいですか?たとえば、ビットフレームライブラリとnumpyを使用して、コントロールフレームヘッダーのすべての異なるセクションのサイズを制御しようとしましたが、実際には何も機能していません。 pythonの現在のSPDYライブラリは、cythonとCのデータ型を使用しており、非常に予測不可能であることがわかりました。純粋なpythonまたは非常に単純に、プロトコルが定義し、ソケットを介して送信するようなものを正確に構築するにはどうすればよいですか?

15
ubiQ

通常、bytearrayクラスがあなたの友達になります(あなたの質問を正しく理解している場合)。ソケット経由で送信できます:

my_bytes = bytearray()
my_bytes.append(123)
my_bytes.append(125)

// my_bytes is b'{}' now

s.send(my_bytes)

プロトコル仕様に従って、バイトごとにバイトを作成します。これは、データを受信するときにも機能します。

data = s.recv(2048)
my_bytes = bytearray(data)

SPDYプロトコルについてはあまり知りませんが、たとえば、制御ビットはメッセージの最初のbit(バイトではありません)です。たとえば、バイナリANDを介してmy_bytesから取得できます。

control_frame = my_bytes[0] & 128

これは、128がバイナリの10000000であるため、バイナリANDが最初のビットのみを提供するためです(各バイトに8ビットがあるため、ゼロが7つあることに注意してください)。

それは物事が手動で行われる方法です。もちろん、適切なプロトコルハンドラの作成には多くの時間がかかるため、ライブラリを使用することをお勧めします。

24
freakish

struct module を使用して、文字列でヘッダー形式を定義し、直接解析することもできます。

パケットを生成するには:

fmt = 'B I 4b'
your_binary_data = pack(fmt, header_data)
sock.sendall(your_binary_data)

ここで、fmtはヘッダー形式を示します( 'B I 4b'は単なるaであり、明らかにSPDYヘッダーでは機能しません)。残念ながら、おそらくより大きなチャンクを解析し、フォーマットに従ってそれらを分割することにより、非バイト指定ヘッダーフィールドを処理する必要があります。

それ以外に、ヘッダーを解析するには:

unpacker = struct.Struct('B I 4b')
unpacked_data = unpacker.unpack(s.recv(unpacker.size))

unpacked_dataには、解析されたデータを含むタプルが含まれます。

struct moduleは、Python値とPythonこのアプローチの効率については保証していませんが、fmt文字列を調整するだけで、さまざまなプロトコルを解析できました。

3
Niko