2009-03-26 12 views
9

私はソケット接続を持ち、相手側のサードパーティのリスナーは非常に構造化された方法でデータが流れることを期待しています。たとえば、メッセージの長さを示す符号なし整数、次にいくつかのフラグが設定または設定解除されている実際のビットフィールドである符号なしバイトが続く、送信されるメッセージのタイプを示す符号なしバイトを探します。Pythonを使ってソケット(またはファイル)にバイナリデータを書き込む

私はこれをどのようにしてPythonで行いますか?私はこのデータを確実に生成し、正しく送信しているかどうかを確認するだけです(つまり、符号付き整数またはそれより悪い文字列ではなく、実際には符号なしバイトを送信しています)。

答えて

11

structモジュールを使用してバッファを作成し、それを書き込みます。

0

ソケットI/Oは、最も低いレベルでは、バイト値の文字列をソケットに読み書きします。これを行うために、書き込む情報をバイト値を含む文字列としてエンコードし、それをソケットに書き込みます。私はスーパーストリングを作成し、一度に1文字を追加することでこれを行います。

readRequest = """""" 
    readRequest += chr(self.transactionID/0x100) # Transaction ID MSB   (0) 
    readRequest += chr(self.transactionID % 0x100) # Transaction ID LSB   (1) 
    readRequest += chr(0)       # Protocol ID MSB (Always 0) (2) 
    readRequest += chr(0)       # Protocol ID LSB (Always 0) (3) 
    readRequest += chr(0)       # Length MSB (Always 0)  (4) 
    readRequest += chr(6)       # Length LSB (Always 6)  (5) 
    readRequest += chr(0)       # Unit ID (Always 0)   (6) 

    readRequest += chr(0x04)      # Function code 4  (0) 
    readRequest += chr(startOffset/0x100)   # Starting offset MSB (1) 
    readRequest += chr(startOffset % 0x100)   # Starting offset LSB (2) 
    readRequest += chr(0)       # Word count MSB  (3) 
    readRequest += chr(2 * nToRead)     # Word count LSB  (4) 

    sockOutfile.write(readRequest) 

を彼らはI/O列に付加できるように文字列にマルチバイト値を変換するには、構造体のモジュールに「パック()」関数を使用します。たとえば、Modbusの/イーサネットは、読み出し要求を作成します。この関数は、1つ以上の単一または複数のバイト値を個々のバイト値の文字列に変換します。

もちろん、この方法はハンマーほど簡単です。文字列内のデフォルトの文字エンコーディングがASCIIではなくUnicodeの場合は、修正する必要があります。

+0

これはお勧めできません。エラーが発生しやすく、保守が難しい。これを行うには、structモジュールがはるかに良い方法です。 – Ferruccio

+0

はい、私は同意する必要があります。残念ながら、私はPythonを学んでいる間にこれを書いて、私がまだCで書いているかのように書いています。 – mkClark

4

Pythonオブジェクトとバイナリ表現(両方向)の間のこれらのトランジションを処理するための非常にエレガントな方法は、Construct libraryを使用しています。

ドキュメントには、その使用例がたくさんあります。私は数年前からシリアル通信プロトコルやバイナリデータのデコードを行ってきました。

関連する問題