1. 为什么使用pack
我们知道,在网络传输过程中,我们的数据都是以二级制的网络报文在进行传输,很多时候,我们多语言之间交互的时候,想在传输的过程中约定传输的头信息,比如常见的http协议 是展示的明文传输的
GET /game HTTP/1.1
Host: sp0.baidu.com
Connection: keep-alive
但很多时候,比如我们要做的是游戏的排行榜,而游戏的分数来自C++,每次游戏结束我们要刷新排行榜,可能我们之间并没有完整的 session会话来确保我们的通信是可靠的,这时,如果我们互相之间约定一个传输协议,比如请求头中那几位是验证信息,哪几位使我们要传输的数据,如果验证不通过,我们就认为是非法来源,直接返回403等状态码,场景大概是这样。进入pack的主题,怎么用。
2. 使用pack和unpack
string pack ( string $format [, mixed $args [, mixed $... ]] )
pack中有多个参数,其中
$format 为格式参数有点类似于c中的print 设置的%s 但是去掉了% 而且更灵活,
字母数字 或者 字母 或者 字母*
a12 或者 c 或者 H*
$args 的个数取决于格式中字母的个数 比如 'a12a13' 就需要两个字符串 分别是12位 和 13 位 位数不足以nul填充
如果是单个字母不跟数字 则为一位类型的字符
如果是单个字母跟上 * 则为该类型任意长度的字符
编码 | 描述 |
---|---|
a | 以NUL字节填充字符串空白 |
A | 以SPACE(空格)填充字符串 |
b | 一个位串 每个字节里位的顺序都是升序 |
B | 一个位串 每个字节里位的顺序都是降序 |
h | 十六进制字符串,低4位在前 一位对应二进制的四位 |
H | 十六进制字符串,高4位在前 |
c | 一个有符号字符 char (8位整数)值 |
C | 一个无符号字符 char (8位整数)值 关于Unicode参阅 U |
s | 有符号短整型(16位,主机字节序) |
S | 无符号短整型(16位,主机字节序) |
n | 一个16位无符号短整型(16位,大端字节序) “网络字节序” |
v | 无符号短整型(16位,小端字节序) |
i | 有符号整型(机器相关大小字节序) |
I | 无符号整型(机器相关大小字节序) |
l | 有符号长整型(32位,主机字节序) |
L | 无符号长整型(32位,主机字节序) |
N | 一个16位无符号长整型(32位,大端字节序) “网络字节序” |
V | 无符号长整型(32位,小端字节序) |
q | 有符号长长整型(64位,主机字节序) |
Q | 无符号长长整型(64位,主机字节序) |
J | 无符号长长整型(64位,大端字节序) |
P | 无符号长长整型(64位,小端字节序) 一个指向空结尾字符串的指针 |
p | 一个执行定长字符串的指针 |
u | 一个无编码的字串 |
U | 一个Unicode字符数字 |
f | 单精度浮点型(机器相关大小) |
d | 双精度浮点型(机器相关大小) |
x | NUL字节 |
X | 回退一字节 |
Z | 以NUL字节填充字符串空白(new in PHP 5.5) |
@ | NUL填充到绝对位置 |
同样的解码函数 unpack
array unpack ( string $format , string $data [, int $offset = 0 ] )
第一个也是格式串,单个字母或者多个字母类型的必须使用 (多个字母 \ 不能省略)
格式名称 \ 格式名称 组成索引数组(好像是从1开始) 或者
格式名称字段名称 \ 格式名称字段名称 组成键值数组
废话不多说 看两个例子
$username = '[email protected]';
$password = 'b123456';
$packdata = pack('SCSa32a32',0x0040,0x00,0x0006, $username, $password );
$unpackdata = unpack('Shead/Cflag/Sflag2/a32word/a32passd/',$packdata);
print_r($unpackdata);
$username = '[email protected]';
$packdata = pack('a32',$username);
$unpackdata = unpack('a*',$packdata);
print_r($unpackdata) ;