装配二进制字符串(pack函数)

时间:2023-01-07 08:06:48

最近看一点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