文档章节

PHP为什么要用pack/unpack

吾爱
 吾爱
发布于 01/15 12:41
字数 844
阅读 47
收藏 1
PHP

pack/unpack详细用法参见:

https://my.oschina.net/goal/blog/195749?p=1#OSC_h3_12

这里只探讨一下为什么会有这两个函数,在什么情况下要用到它们。

首先,了解下php里的字符串string,一般情况下我们用字符串是用来表示一个人类可读的文本,简单来讲就是用来表示一串文字,例如:

$str = 'abc';

abc 是3个字母组成的一串文本,其实对于计算机来说,它就是一串二进制而已 01010101... ,但是为了便于代码中处理,一般是按字节为单位来处理,一个字节8位。以上面的 $str 来说,转换成字节序列就是:

[ord('a'),ord('b'),ord('c')]
// [97,98,99]

问题来了,假设我们需要跟外部服务打交道,它要求我们传一条消息,这条消息是3各字节,对应字节码分别是 97 98 99,巧了,正好对应 abc 三个字母,我们可以直接通过 $msg = 'abc'; 生成这条消息,并直接发送给外部服务。

但是,如果它要求的是 0x01 0x02 0x03 呢?(这里用的是十六进制表示),你能打出来吗?$msg = ???

这时候需要拐个弯,你可以这样写 $msg = chr(0x01).chr(0x02).chr(0x03); 在这种足够简单的情形下可以达到要求,但是不幸的是,一般网络通信中,如果是自定义协议,一般会涉及更多的数据类型并且还有大端小端问题,关于大端小端也不做详细描述,可自行搜索相关资料。

比如啊,对方要求传一条消息,这个消息由2部分组成,前两个字节固定为 0x220x33 后面紧跟一个在c语言中是无符号16位整型,并且这个整型是小端存储,好了,你可以构建这条消息:

$msg = chr(0x22).chr(0x33);
//无符号16位整型?两个字节? 小端?
$num = 0x0532; //假设这是要传的16位整型,那么怎么转换成两个字节的无符号小端字节序列?
//经过研究,了解了小端字节序的意思,可以这样构建
$msg .= chr(0x32).chr(0x05);

是不是很麻烦?这时候就可以用pack来做这个事了,一行代码搞定而已。

$msg = pack('C2v',0x22,0x33,0x0532);

是不是很方便?我们只需要了解pack第一个参数怎么设置就可以了,这里简单解释一下

'C2' 的意思是,将后面前两个参数,即 0x22 0x33 ,作为无符号char类型打包到字符串中,紧接着 'v' 的意思是,将后面的一个参数,作为无符号short类型(16位整型,两个字节,小端),打包到字符串中,最终得到一个4字节的字符串,就可以发给对方了。

unpack同理,是用来解析对方传过来的二进制字符串,前提是双方约定好打包规则,比如如果要解包上面的 $msg ,只需要

$data = unpack('C2head/vnumber',$msg);

注意,每个部分你可以用 '/' 分割,然后,每个解析规则后面都可以跟一个名字作为解析结果数组的key,最终得到

Array
(
    [head1] => 34
    [head2] => 51
    [number] => 1330 //这里php默认会以10进制的形式显示,其实等于0x0532
)

© 著作权归作者所有

共有 人打赏支持
吾爱
粉丝 143
博文 264
码字总数 89585
作品 0
后端工程师
PHP: pack/unpack补遗

pack/unpack的介绍和使用加上这篇就第三篇了。确实知识点比较多,这篇算是收尾之作吧。仔细去文档上看pack/unpack的格式化字符说明,就会发现s, S, i, I, l, L, f, d都没有对应的大端序和小端...

陈亦
2014/02/23
0
11
PHP: chr和pack、unpack那些事

PHP是一门很灵活的语言。正因为它太灵活了,甚至有些怪异,所以大家对它的评价褒贬不一。其实我想说的是,任何一门语言都有它自身的哲学,有它存在的出发点。PHP为Web而生,它以快速上手、快...

陈亦
2014/02/23
0
31
php pack 和 unpack 函数

输出: PHP php 用unpack 函数后得到的就是那3个数作为键值的数组,那怎么把这个数组当作pack函数的三个参数传进去 我用了eval 函数,但是结果是false,厉害的帮忙解决下,不胜感激,像这种参...

李佳顺
2014/01/08
305
4
msgpack 真的比 protobuf buffers 快 4 倍吗?

hprose serialize Runtime:0.2334s json encode Runtime:15.2883s serialize Runtime:0.7090s msgpack_pack Runtime:0.6883s hprose unserialize Runtime:0.5439s json decode Runtime:24.29......

andot
2015/04/18
3.4K
4
用socket方式与服务器通信,php如何处理网络字节顺序

最近搞一个用socket与服务端通信的东西,之前完全没接触过,大概意思我说一下,希望有人能帮帮忙。 数据传输格式:报文头+报文体 服务端要求报文头中int类型字段用网络字节顺序,我大概查了下...

dongyao
2013/12/01
1K
5

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java并发备忘

不安全的“先检查后执行”,代码形式如下: if(条件满足){ //这里容易出现线程安全问题//doSomething}else{//doOther} 读取-修改-写入 原子操作:使用CAS技术,即首先从V中读取...

Funcy1122
今天
0
0
SpringBoot2.0 停机

最近新建了个SpringBoot2.0的项目,因为原来一直使用的是传统的Tomcat部署war包的形式,所以这次SpringBoot内置Tomcat部署jar包的时候遇到了很多问题。其中一个就是因为没有外置的Tomcat容器...

Canaan_
昨天
0
1
Confluence 6 外部参考

一个外部参考的意思是任何站点链接到你 Confluence 的实例。任何时候当 Confluence 的用户单击这个外部链接的时候,Confluence 可以记录这次单击为参考。 在默认的情况下,外部链接的参考链接...

honeymose
昨天
0
0
Android中的设计模式之抽象工厂模式

参考 《设计模式解析》 第十一章 Abstract Factory模式 《设计模式:可复用面向对象软件的基础 》3.1 Abstract Factory 抽象工厂 对象创建型模式 《Android源码设计模式解析与实战》第6章 创...

newtrek
昨天
0
0
Redis | 地理空间(GEO)的一个坑

Redis的地理空间(Geo)是个好东西,轻轻松松的就可以把地图描点的问题处理了, 最近却遇到一个坑...Redis采用的Msater-Slave模式, 运用GEORADIUS在salve读取对应的数据,新增了从节点但是从不返...

云迹
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部