1. 程式人生 > >python 實現和 C的IP socket通訊如何打包資料?

python 實現和 C的IP socket通訊如何打包資料?

2011-12-28

伺服器端是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)

會將兩個整形以二進位制打到包中。程式執行結果:

'x01x00x00x00x02x00x00x00'

格式和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中可以增加一個長度描述。如”6i”表示6個整形。”20s”表示20個位元組長度的字串,而“20c”表示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)
'x01x00x00x00test 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)
'x00x00x00x02x01x00x00x00x02x00x00x00'

4.例項 給一個二進位制header字尾二進位制資料

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,可以pack到一個buf中

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語言的二進位制通訊,解決跨語言通訊問題

參考:

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源