最近看一点python的代码,发现struct这个包在处理网络编程上非常强大,pack和unpack函数能很轻松地将数据组包拆包,如下所示:
#! /usr/bin/env python import socket, struct, time, re if __name__ == '__main__': num1 = 5 num2 = 10 str1 = 0x00001000 str2 = 0x00002000 cha1 = 3 cha2 = 65 pack_res = struct.pack('!HHIIBB', num1, num2, str1, str2, cha1, cha2) print "after pack " print "pack_res", pack_res n1,n2,s1,s2,c1,c2 = struct.unpack("!HHIIBB", pack_res) print "after unpack" print "n1 = ", n1 print "n2 = ", n2 print "s1 = ", s1 print "s2 = ", s2 print "c1 = ", c1 print "c2 = ", c2 ''' after pack pack_res ??????????... after unpack n1 = 5 n2 = 10 s1 = 4096 s2 = 8192 c1 = 3 c2 = 65 '''官方手册有格式参数的说明,摘录如下,其中感叹号表示网络序字节流,H代表无符号短整型,B代表无符号字符,I代表无符号整形。
Character | Byte order | Size | Alignment |
---|---|---|---|
@ | native | native | native |
= | native | standard | none |
< | little-endian | standard | none |
> | big-endian | standard | none |
! | network (= big-endian) | standard | none |
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) |
python语法支持函数返回多个结果值,而php没有这种性质,所以php的unpack函数使用上稍有区别,比如同样是实现上面的功能,php的写法如下:
<?php $num1 = 5; $num2 = 10; $str1 = 0x00001000; $str2 = 0x00002000; $cha1 = 3; $cha2 = 65; $pack_res = pack("nnNNCC",$num1,$num2,$str1,$str2,$cha1,$cha2); echo "after pack\n"; echo "pack_res=".$pack_res; $unpack_res = unpack("n2num/N2str/C*cha",$pack_res); var_dump($unpack_res); /* after pack ????????? pack_res=array(6) { ["num1"]=> int(5) ["num2"]=> int(10) ["str1"]=> int(4096) ["str2"]=> int(8192) ["cha1"]=> int(3) ["cha2"]=> int(65) } */ ?>可以看到我们unpack的时候,是打包到一个关联数组中,关联数组的内容在format格式化时说明,还有一点需要注意的是,php与python的格式化参数不一致的,需要参照各自的定义。比如python的HIB分别对应php的nNC。php的格式化参数如下:
Code | Description |
---|---|
a | NUL-padded string |
A | SPACE-padded string |
h | Hex string, low nibble first |
H | Hex string, high nibble first |
c | signed char |
C | unsigned char |
s | signed short (always 16 bit, machine byte order) |
S | unsigned short (always 16 bit, machine byte order) |
n | unsigned short (always 16 bit, big endian byte order) |
v | unsigned short (always 16 bit, little endian byte order) |
i | signed integer (machine dependent size and byte order) |
I | unsigned integer (machine dependent size and byte order) |
l | signed long (always 32 bit, machine byte order) |
L | unsigned long (always 32 bit, machine byte order) |
N | unsigned long (always 32 bit, big endian byte order) |
V | unsigned long (always 32 bit, little endian byte order) |
f | float (machine dependent size and representation) |
d | double (machine dependent size and representation) |
x | NUL byte |
X | Back up one byte |
@ | NUL-fill to absolute position |