Pythonモジュール-struct(バイトストリーム、パケット分割実装)
6178 ワード
pythonは6種類のデータ型,文字列,整数,浮動小数点数,リスト,メタグループ,辞書のみを定義していることを知っています.しかし、C言語にはバイト型の変数がありますが、pythonではどのように実現すればいいのでしょうか.特にネットワーク上でデータ転送を行うには、この点が重要です.
pythonはstructモジュールを提供して変換を提供します.このモジュールのいくつかの方法について説明します.
struct.pack():
struct.packは、Pythonの値をフォーマットに基づいて文字列に変換するために使用されます(Pythonにはバイト(Byte)タイプがないため、ここでの文字列はバイトストリーム、またはバイト配列と理解できます).その関数のプロトタイプはstruct.pack(fmt, v1, v2, ...),パラメータfmtはフォーマット文字列であり、フォーマット文字列に関する情報は以下に説明する.v1, v2, ...変換するpython値を表します.次の例では、2つの整数を文字列(バイトストリーム)に変換します.
>>> import struct >>> a=20 >>> b=400 >>> str=struct.pack('ii',a,b)#はバイトストリームに変換され、文字列であるが、ネットワーク上で伝送可能>>print len(str)#iiは、2つのint 8#が長さ8バイトで見えることを示し、ちょうど2つのint型データの長さ>>print str#バイナリが文字化けし>>print repr(str)'x 14x 00x 00x 00x 00x 00x 90x 01x 00x 00x 00x 00'#のうち16進数の0 x 0000014、0 x 0001009はそれぞれ20と400>>
struct.unpack():
次に、上記の例を実行します.
>>> a1,a2=struct.unpack('ii',str) >>> print 'a1',a1 a1 20 >>> print 'a2=',a2 a2= 400
python実装とCのIP socket通信はどのようにデータをパッケージしますか?
サーバ側はC/C++書き込みで、pythonはクライアントがメッセージを送信し、通信するために使用されます.このモードは圧力テストに使用でき,プロトコルの修正が容易である.
質問:
1.pythonはパケットとバイナリの操作にC言語ほど便利ではありません.データ型に対してどのようにパッケージしますか.
pythonは便利なスクリプト言語として、C言語と一つ一つ対応できない数少ないデータ型を提供しています.パケットを打つときは、C言語のようにポインタを移動したり操作したりすることはできません.
2.長くなった文字列変数をpythonパッケージにどのように打つか
structで文字列をフォーマットするには長さを指定する必要がありますが、文字列の長さが固定されていない場合は、どのようにパッケージをパッケージ化して解くのでしょうか.
解決策:pythonのstructでパッケージ化します.struct提供pack,unpack,pack_into,unpack_from関数は、C言語に対応するデータformatを提供します.
3.バイナリデータのパッケージ化方法
1.バイナリデータのフォーマット
例:
2つの整形は2進数でパッケージに打たれます.プログラム実行結果:
フォーマットとC言語タイプの対応関係:
Format
C Type
Python type
Standard size
Notes
x
pad byte
no value
c
char
string of length 1
1
b
signed char
integer
1
(3)
B
unsigned char
integer
1
(3)
?
_Bool
bool
1
(1)
h
short
integer
2
(3)
H
unsigned short
integer
2
(3)
i
int
integer
4
(3)
I
unsigned int
integer
4
(3)
l
long
integer
4
(3)
L
unsigned long
integer
4
(3)
q
long long
integer
8
(2), (3)
Q
unsigned long long
integer
8
(2), (3)
f
float
float
4
(4)
d
double
float
8
(4)
s
char[]
string
p
char[]
string
P
void *
integer
(5), (3)
ここでpはpascalタイプの文字列、sはc言語タイプの文字列である.formatには長さの説明を追加できます.例えば「6 i」は6つの整形を表す.20 sは20バイトの文字列を表し、20 cは20バイトを表す.formatはバイトシーケンスを指定することもできます.
Character
Byte order
Size
Alignment
@
native
native
native
=
native
standard
none
<
little-endian
standard
none
>
big-endian
standard
none
!
network (= big-endian)
standard
none
ネットバイト順は一般的に「!先頭に立つ.
2.文字列変数のパッケージ化
フォーマット文字列を再フォーマットし、変数の長さを入力できます.
例
単純なパッケージの場合、stackoverflowは変数文字列を打つ方法を示します.
3.パッケージバイナリ
バイナリパケットは、フォーマットデータの後ろにバイナリを直接ドロップすることができ、文字列で処理することができます.
4.インスタンスはバイナリヘッダ接尾辞バイナリデータを与える
suffixは接尾辞のバイナリまたは文字列であり、lengはheaderで接尾辞の長さを記述するために使用される変数であり、typeはcmdtypeである.
またはpack_into、1つのbufにpackできます
まとめ:
pythonライブラリstructでC言語のバイナリ通信に完全に対応し、言語間通信の問題を解決できます.
pythonはstructモジュールを提供して変換を提供します.このモジュールのいくつかの方法について説明します.
struct.pack():
struct.packは、Pythonの値をフォーマットに基づいて文字列に変換するために使用されます(Pythonにはバイト(Byte)タイプがないため、ここでの文字列はバイトストリーム、またはバイト配列と理解できます).その関数のプロトタイプはstruct.pack(fmt, v1, v2, ...),パラメータfmtはフォーマット文字列であり、フォーマット文字列に関する情報は以下に説明する.v1, v2, ...変換するpython値を表します.次の例では、2つの整数を文字列(バイトストリーム)に変換します.
>>> import struct >>> a=20 >>> b=400 >>> str=struct.pack('ii',a,b)#はバイトストリームに変換され、文字列であるが、ネットワーク上で伝送可能>>print len(str)#iiは、2つのint 8#が長さ8バイトで見えることを示し、ちょうど2つのint型データの長さ>>print str#バイナリが文字化けし>>print repr(str)'x 14x 00x 00x 00x 00x 00x 90x 01x 00x 00x 00x 00'#のうち16進数の0 x 0000014、0 x 0001009はそれぞれ20と400>>
struct.unpack():
次に、上記の例を実行します.
>>> a1,a2=struct.unpack('ii',str) >>> print 'a1',a1 a1 20 >>> print 'a2=',a2 a2= 400
python実装とCのIP socket通信はどのようにデータをパッケージしますか?
サーバ側はC/C++書き込みで、pythonはクライアントがメッセージを送信し、通信するために使用されます.このモードは圧力テストに使用でき,プロトコルの修正が容易である.
質問:
1.pythonはパケットとバイナリの操作にC言語ほど便利ではありません.データ型に対してどのようにパッケージしますか.
pythonは便利なスクリプト言語として、C言語と一つ一つ対応できない数少ないデータ型を提供しています.パケットを打つときは、C言語のようにポインタを移動したり操作したりすることはできません.
2.長くなった文字列変数をpythonパッケージにどのように打つか
structで文字列をフォーマットするには長さを指定する必要がありますが、文字列の長さが固定されていない場合は、どのようにパッケージをパッケージ化して解くのでしょうか.
解決策:pythonのstructでパッケージ化します.struct提供pack,unpack,pack_into,unpack_from関数は、C言語に対応するデータformatを提供します.
3.バイナリデータのパッケージ化方法
1.バイナリデータのフォーマット
例:
import struct
fmt="ii"
buf = struct.pack(fmt,1,2)
print repr(buf)
2つの整形は2進数でパッケージに打たれます.プログラム実行結果:
'\x01\x00\x00\x00\x02\x00\x00\x00'
フォーマットとC言語タイプの対応関係:
Format
C Type
Python type
Standard size
Notes
x
pad byte
no value
c
char
string of length 1
1
b
signed char
integer
1
(3)
B
unsigned char
integer
1
(3)
?
_Bool
bool
1
(1)
h
short
integer
2
(3)
H
unsigned short
integer
2
(3)
i
int
integer
4
(3)
I
unsigned int
integer
4
(3)
l
long
integer
4
(3)
L
unsigned long
integer
4
(3)
q
long long
integer
8
(2), (3)
Q
unsigned long long
integer
8
(2), (3)
f
float
float
4
(4)
d
double
float
8
(4)
s
char[]
string
p
char[]
string
P
void *
integer
(5), (3)
ここでpはpascalタイプの文字列、sはc言語タイプの文字列である.formatには長さの説明を追加できます.例えば「6 i」は6つの整形を表す.20 sは20バイトの文字列を表し、20 cは20バイトを表す.formatはバイトシーケンスを指定することもできます.
Character
Byte order
Size
Alignment
@
native
native
native
=
native
standard
none
<
little-endian
standard
none
>
big-endian
standard
none
!
network (= big-endian)
standard
none
ネットバイト順は一般的に「!先頭に立つ.
2.文字列変数のパッケージ化
フォーマット文字列を再フォーマットし、変数の長さを入力できます.
例
>>> a="test buf"
>>> leng=len(a)
>>> fmt="i%ds"%leng
>>> buf=struct.pack(fmt,1,a)
>>> print repr(buf)
'\x01\x00\x00\x00test buf'
単純なパッケージの場合、stackoverflowは変数文字列を打つ方法を示します.
# ,
struct.pack("I%ds" % (len(s),), len(s), s)
#
def unpack_helper(self,fmt, data):
size = struct.calcsize(fmt)
return struct.unpack(fmt, data[:size]), data[size:]
fmt_head="!6i"
head,probuf = self.unpack_helper(fmt_head,buf)
3.パッケージバイナリ
バイナリパケットは、フォーマットデータの後ろにバイナリを直接ドロップすることができ、文字列で処理することができます.
>>> fmt1="!i"
>>> buf2=struct.pack(fmt1,2)+buf1
>>> print repr(buf2)
'\x00\x00\x00\x02\x01\x00\x00\x00\x02\x00\x00\x00'
4.インスタンスはバイナリヘッダ接尾辞バイナリデータを与える
suffixは接尾辞のバイナリまたは文字列であり、lengはheaderで接尾辞の長さを記述するために使用される変数であり、typeはcmdtypeである.
def getheader(msgtype,leng,suffix):
magic = 0
sn=0
ori_res=0
# mtype=msgtype
param = 0
#mleng = leng
fmt="!6i"
buf = struct.pack(fmt,magic,sn,ori_res,msgtype,param,leng)+suffix
またはpack_into、1つのbufにpackできます
def getheader(msgtype,leng,suffix):
magic = 0
sn=0
ori_res=0
# mtype=msgtype
param = 0
#mleng = leng
buf = create_string_buffer(24+leng)
fmt = "!6i%ds"%leng
print fmt
struct.pack_into(fmt,buf,0,magic,sn,ori_res,msgtype,param,leng,suffix)
#print repr(buf.raw)
#for test
#b = struct.unpack_from(fmt,buf)
#print b
return buf
まとめ:
pythonライブラリstructでC言語のバイナリ通信に完全に対応し、言語間通信の問題を解決できます.