• 字符的二进制,php的pack与unpack


    $curl = curl_init ();
    curl_setopt($curl, CURLOPT_URL ,  'http://mh.18touch.com/restful/magic');
    curl_setopt($curl, CURLOPT_PORT, 80);
    //curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 50);
    //curl_setopt($curl, CURLOPT_TIMEOUT_MS, 50);
    //curl_setopt($curl, CURLOPT_HEADER, true);
    //curl_setopt($curl, CURLINFO_HEADER_OUT , true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0);
    curl_setopt($curl, CURLOPT_POST, true);
    //$p_data=file_get_contents('xyl.zip');
    
    $p_data ="test 123";
    $data_length = strlen($p_data);
    
    for($i=0;$i<$data_length;$i++){
    	$byte[] = pack('H2',dechex(ord($p_data[$i])));
    }
    $str = implode('',$byte);
    $data_length = strlen($str);
    $p_data =$str;
    
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Length: $data_length","Content-Type: application/octet-stream"));
    curl_setopt($curl, CURLOPT_POSTFIELDS, $p_data);
    //curl_setopt($curl, CURLOPT_NOBODY , true);
    $a = curl_exec($curl);
    //$b = curl_getinfo($curl);
    var_dump($a);
    

     上面通过截取包,发现里面的内容是一样的,都是传输的字符串test 123。如果把pack的打包改成h,就会使显示发送的是16进制表示的数,都是对应的字符串的十六进制数的高地位相反,47 67...,这样的序列构不成正确的http协议传输的ascii吗值所以显示为十六进制的表示形式,传递的还是二进制数。上面的字符串只是把二进制数表示为字符串了。

    pack h 的意思是把后面的当16进制字符串,你传入整形12与字符串12是一样的。要求传入一个16进制内的字符。

    为了避免混淆,我把“test 123”这样的字符串定义为表示型二进制字符串。

    test123 对应的“10101010101010101010”这样的字符串定义为存储型二进制字符串。(要注意的是存储的肯定是二进制,而不是字符串!!)

    上面的可以看做是表示型二进制字符串“t”,它的存储型字符串是“10010110”,它的二进制值是11010110。

    所以http里只有二进制传输!

    下面就是传输二进制的伪代码,其实底层传输的是其对应的存储层。

    <?php
    header("charset=utf-8;");
     
    function StrToBin($str){
        //1.列出每个字符
        $arr = preg_split('/(?<!^)(?!$)/u', $str);
        //2.unpack字符
        foreach($arr as &$v){
            $temp = unpack('H*', $v);
            $v = base_convert($temp[1], 16, 2);
            unset($temp);
        }
     
        return join(' ',$arr);
    }
     
    function BinToStr($str){
        $arr = explode(' ', $str);
        foreach($arr as &$v){
            $v = pack("H".strlen(base_convert($v, 2, 16)), base_convert($v, 2, 16));
        }
     
        return join('', $arr);
    }
     
    echo StrToBin("里面23");
    echo '<br/>';
    echo BinToStr(StrToBin("里面23"));
    

    unpack与ord类似,得到表示型字符串的底层二进制值,拿到二进制值会后,我们可以通过base_convert转化为存储型二进制字符串。

    unpack('H*', '9') 的过程是先得到'9'的底层存储值ord('9')=112,然后按H的形式返回(又从二进制值变成表示型字符串),所以还要把进行dechex(112)=39;最后得到字符串‘9’的H表示为‘39’,返回array(1=>"39")。

    他的意思是得到表示型字符‘9’的底层二进制值的H表示值“39”。上例的伪传输二级制又通过base_convert把H表示的字符串转化为B表示的字符串“00111001”

    pack与chr类似,不过更高级,可以打包表示型字符串得到存储值,存储值其实就是二进制,他不是字符串~

    strlen(base_convert(“00111001”, 2, 16)) = strlen(“39”) = 2

    pack(“H2”,“39”)的意思是把H表示型字符串“39”打包成一个H格式的值及0x39 = 112 = 表示型字符“9”

    这里的概念很容易搞晕~~~

    简单的将,unpack拆包,得到存储值(或者直接拿pack打包后的结果,其实也是存储值),然后通过fomat来从重新包装表示。给一个pack打包的长串,根据fomat拆包为多个字段的表示。

    pack组装,就是把给他的东西,按照fomat来转化为存储值。给多个就把存储值组装到一起!

    存储值就是二进制数,在php手册里面叫binary string ,极其容易跟存储型表示的二进制字符串弄混~

  • 相关阅读:
    在FreeBSD中pkg包管理器使用实例
    租了一台华为云耀云服务器,却直接被封公网ip,而且是官方的bug导致!
    Java8 Stream对集合的一些应用
    idea 编码UTF-8 设置
    Java RSA非对称加密算法实现
    分库分表 策略 临时
    springboot+dubbo + zookeeper 案例
    跟着华为,学数字化转型(6):一把手工程
    跟着华为,学数字化转型(5):数据保护和业务决策
    跟着华为,学数字化转型(4):数据采集
  • 原文地址:https://www.cnblogs.com/kudosharry/p/4081004.html
Copyright © 2020-2023  润新知