PHP爲何要用pack/unpack

pack/unpack詳細用法參見:php

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

這裏只探討一下爲何會有這兩個函數,在什麼狀況下要用到它們。網絡

首先,瞭解下php裏的字符串string,通常狀況下咱們用字符串是用來表示一我的類可讀的文本,簡單來說就是用來表示一串文字,例如:函數

$str = 'abc';

abc 是3個字母組成的一串文本,其實對於計算機來講,它就是一串二進制而已 01010101... ,可是爲了便於代碼中處理,通常是按字節爲單位來處理,一個字節8位。以上面的 $str 來講,轉換成字節序列就是:.net

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

問題來了,假設咱們須要跟外部服務打交道,它要求咱們傳一條消息,這條消息是3各字節,對應字節碼分別是 97 98 99,巧了,正好對應 abc 三個字母,咱們能夠直接經過 $msg = 'abc'; 生成這條消息,並直接發送給外部服務。code

可是,若是它要求的是 0x01 0x02 0x03 呢?(這裏用的是十六進制表示),你能打出來嗎?$msg = ???blog

這時候須要拐個彎,你能夠這樣寫 $msg = chr(0x01).chr(0x02).chr(0x03); 在這種足夠簡單的情形下能夠達到要求,可是不幸的是,通常網絡通訊中,若是是自定義協議,通常會涉及更多的數據類型而且還有大端小端問題,關於大端小端也不作詳細描述,可自行搜索相關資料。字符串

好比啊,對方要求傳一條消息,這個消息由2部分組成,前兩個字節固定爲 0x220x33 後面緊跟一個在c語言中是無符號16位整型,而且這個整型是小端存儲,好了,你能夠構建這條消息:get

$msg = chr(0x22).chr(0x33);
//無符號16位整型?兩個字節? 小端?
$num = 0x0532; //假設這是要傳的16位整型,那麼怎麼轉換成兩個字節的無符號小端字節序列?
//通過研究,瞭解了小端字節序的意思,能夠這樣構建
$msg .= chr(0x32).chr(0x05);

是否是很麻煩?這時候就能夠用pack來作這個事了,一行代碼搞定而已。string

$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
)
相關文章
相關標籤/搜索