TCP接收十六进制数据后再以十六进制发送给设备
swoole 2018-06-08 13:53:59

一、TCP接收十六进制的字符串以后:

PHP Code复制内容到剪贴板
  1.     /** 
  2.      * TCP协议的端口收到数据 
  3.      * @param swoole_server $serv 
  4.      * @param $fd 
  5.      * @param $from_id 
  6.      * @param $data 
  7.      * @return bool 
  8.      */  
  9.     public function onTcpReceive(swoole_server $serv$fd$from_id$data)  
  10.     {  
  11.         $receiveStr = $data;  
  12.             $num = rand(0, 10); // 随机数(保留)  
  13.             $address = $receive[4]; // 控制器地址(保留)  
  14.             $door = $receive[5]; // 门编号  
  15.             $command = $receive[3]; //指令先用控制器里发来的  
  16.             // 包头  
  17.             $pack_head = [  
  18.                 "02",  
  19.                 $num,  
  20.                 $command,  
  21.                 $address,  
  22.                 $door,  
  23.             ];  
  24.             // 包体  
  25.             $pack_body = [  
  26.                 $command  
  27.             ];  
  28.             $sendData = $this->getSendData($pack_head,$pack_body);  
  29.             return $sendData;  
  30.   
  31.     }  
  32.   
  33.   
  34.     function getSendData(array $headarray $body = array())  
  35.     {  
  36.         $length = count($body); // 包体长度  
  37.         $hight = ($length & 0xff00) >> 8; // 高位右移8个位  
  38.         $low = $length & 0x00ff; // 低位  
  39.         $head[] = $low;     // 数据长度低位  
  40.         $head[] = $hight;   // 数据长度高位  
  41.   
  42.         // 将包头和包体 合并  
  43.         $data = $body?array_merge_recursive($head$body):$head;  
  44.   
  45.         $check = $this->getCheckVal($data); // 获取校验值  
  46.         $data[] = $check;  
  47.         $data[] = "03";  
  48.   
  49.         return $this->get_pack($data);  
  50.     }  
  51.   
  52.     function get_pack($data)  
  53.     {  
  54.         $pack = "";  
  55.         foreach ($data as $k => $d) {  
  56.             $pack .= pack("C*"$d); // 十六进制应答  
  57.         }  
  58. //        echo "十六进制转为字符串应答的数据:" . bin2hex($pack) . PHP_EOL;  
  59.         return $pack;  
  60.     }  
  61.   
  62.     /** 
  63.      * 根据数组中所有值 获取校验值 
  64.      * @param array $data 
  65.      * @return float|int|string 
  66.      */  
  67.     function getCheckVal(array $data)  
  68.     {  
  69.         // 将第一个放进循环中会报错,单独将第一个字节先取出来  
  70.         $check = hexdec("0x" . $data[0]);  
  71.         // 所有数据 进行异或运算,从数组中的第二个开始 (测试数据,减掉包尾)  
  72.         $i = 0;  
  73.   
  74.         // 这里的data是十六进制的字符串,要先将它以0x组合出来16进制的字符串,再转换为10进制的数字用以运算  
  75.         // 得到的结果是十进制的校验值  
  76.         foreach ($data as $d){  
  77.             $i++;  
  78. //            echo "打印加入运算的字符:" . $d.PHP_EOL;  
  79.             if($i == 1){  
  80.                 $check = $d;  
  81.             }else{  
  82.                 $check ^= $d;  
  83.             }  
  84.         }  
  85.         //    $check = dechex($check); // 结果:是十进制的,最后,将十进制转十六进制字符,这里不需要转换十六进制,因为最后还需要将数据放到pack方法中转换  
  86.         return $check;  
  87.     }  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

TCP receive的数据,转换:

1、将二进制解包为十进制:

PHP Code复制内容到剪贴板
  1. $data = unpack("C*"$data); // 从二进制字符流对数据进行解包,打印出来的数据是十进制的展示  

 

2、把 二进制字节流 (机器发来的)转换为十六进制值:(可以用pack转换回去)

PHP Code复制内容到剪贴板
  1. $data = bin2hex($data); // 将原始数据转换成16进制的字符串,就是机器发送过来的原数据了  

 

机器发来的都需要用bin2hex转换为十六进制我们常用的字符串,如果需要机器发送命令可以先写成字符串,再转换:

PHP Code复制内容到剪贴板
  1. pack("H*",bin2hex($data)) ;  

 

场景:

塔吊发送过来的命令是:a55a3101010671714ac9130403102a2b01f40000000013380bb8a4000000000000020000000000000000010056cc33c33c

我们在client中模拟发送命令:

PHP Code复制内容到剪贴板
  1. $str = 'a55a3101010671714ac9130403102a2b01f40000000013380bb8a4000000000000020000000000000000010056cc33c33c';  
  2. // 模拟机器发送命令  
  3. $DeviceSendData = pack("H*",$str);  

 

接收服务器时对数据转换为正常显示的十六进制字符串,打印原始数据时,会显示乱码:

PHP Code复制内容到剪贴板
  1. public function onReceive($serv$fd$from_id$data)  
  2. {  
  3.     echo date("Y-m-d H:i:s") ."原始数据 => "$data."\n";  
  4.   
  5.     echo date("Y-m-d H:i:s") ."转换后数据 => ". bin2hex($data)."\n\n\n";  
  6.       
  7. }  

 

 

 

3、如果需要对数据进行异或运算,要使用十进制的数据

1) 十六进制转十进制:

PHP Code复制内容到剪贴板
  1. $byte = "fe";  
  2. $data = hexdec("0x".$byte);  

 

2)转换完毕后 再进行异或运算:

注意点:如果是数组循环,请将第一组先取出来,否则会出现warning

PHP Code复制内容到剪贴板
  1. $data = array("02","df","2c","00","01","01","00","01","f0","03");  
  2. function get_pack_header(array $data){  
  3.     $length = count($data);  
  4.     // 将第一个放进循环中会报错,单独将第一个字节先取出来  
  5.     $header = hexdec("0x".$data[0]);  
  6.   
  7.     // 去掉包尾的两字节,把所有校验位字节前面的所有数据 进行异或运算,从数组中的第二个开始  
  8.     for ($i = 1; $i < $length-2; $i++){  
  9.         $header ^= hexdec("0x".$data[$i]); // 十六进制转换为十进制,再进行异或计算  
  10.     }  
  11.   
  12.     $header = dechex($header); // 结果:f0 , 把十进制转换为十六进制。  
  13.     return $header;  
  14. }  

 

本文来自于:http://www.yoyo88.cn/study/swoole/311.html

下一篇 进制问题
Powered by yoyo苏ICP备15045725号