Home >Backend Development >PHP Tutorial >高手来,关于php中socket的问题!

高手来,关于php中socket的问题!

WBOY
WBOYOriginal
2016-06-23 13:36:21846browse

一个硬件往服务器端口上发送数据(抓包软得到的是正确的16进制),通过抓包软件抓取的数据是正常的(16进制),然而通过php的socket接受到的数据(通过转换后也是16进制,未转换是乱码),下面贴上代码,请高手帮忙看下哪里错了。为什么php的socket获取的数据和抓包软件获取的不一样

通过抓包软件获取的正确代码是(16进制的):FA 01 01 FF AA 03 00 01 00 0B 00 00 00 A3
通过php socket获得的数据(通过dechex(),ord()转换后的,和软件抓取的不一样,是错误的):fa 7 25 2 fa 2 0 9 f6 4 2c 88 fa 1

下面贴上php的socket代码:

<?phperror_reporting(E_ALL);set_time_limit(0);ini_set("allow_call_time_pass_reference",true);//监听端口$PORT = 8888;//最大连接池$MAX_USERS = 50000;//创建监听端口//$sock = socket_create_listen($PORT);$commonProtocol = getprotobyname("tcp");$sock = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);@socket_bind($sock, '192.168.1.101', 8888);@socket_listen($sock);if (!$sock){    exit(1);}//不阻塞socket_set_nonblock($sock);$connections = array();$input = array();$close = array();while (true){	//sleep(3);    $readfds = array_merge($connections, array($sock));    $writefds = array();    //选择一个连接,获取读、写连接通道    if (socket_select($readfds, $writefds, $e = null, $t=60))    {        foreach ($readfds as $rfd)        {            //如果是当前服务端的监听连接            if ($rfd == $sock)            {                //接受客户端连接                $newconn = socket_accept($sock);                $i = (int)$newconn;                $reject = '';                if (count($connections) >= $MAX_USERS)                {                    $reject = "Server full. Try again later.\n";                                   }                                //将当前客户端连接放如socket_select选择                $connections[$i] = $newconn;                //输入的连接资源缓存容器                $writefds[$i] = $newconn;                               //连接不正常                if ($reject)                {                                      $close[$i] = true;                }                else                {                    echo "Welcome to the PHP Chat Server!\n";                                  }                               //初始化当前连接读取内容的缓存容器                $input[$i] = "";                continue;            }            //客户端连接            $i = (int)$rfd;            //读取            $tmp = @socket_read($rfd, 14, PHP_NORMAL_READ);            if (!$tmp)            {                //读取不到内容                              print "connection closed on socket $i\n";                close($i);                continue;            }            $input[$i] .= $tmp;            $tmp = substr($input[$i], -1);            /*if ($tmp != "\r" && $tmp != "\n")            {                // no end of line, more data coming                continue;            }*/            $line = trim($input[$i]);            $input[$i] = "";            echo 'Client >>'.$line."\r\n";												$data=str_split($line);  print_r($data); echo "\r\n";						//$data = explode("\t",$line);			//$data=str_split($data);			foreach($data as $v){			 echo dechex(ord($v))."\t";			 			 }			 echo "\r\n";															socket_getpeername($connections[$i],&$remoteIP,&$remotePort);echo $remoteIP."\r\n";echo $remotePort."\r\n";//$data=str_split($buffer);//print_r($data);$str="\xFA\x01\x01\xFF\xAA\xAA\x00\x01\x00\x00\x00\x00\x00\x01"; socket_send($connections[$i],$str,strlen($str),0);																		        }        foreach ($writefds as $wfd)        {            $i = (int)$wfd;            $w = socket_write($wfd, "hello");        }    }   }function close($i){    global $connections, $input, $close;    socket_shutdown($connections[$i]);    socket_close($connections[$i]);    unset($connections[$i]);    unset($input[$i]);       unset($close[$i]);}?>


回复讨论(解决方案)

完全模拟你的现场和代码

$str="\xFA\x01\x01\xFF\xAA\xAA\x00\x01\x00\x00\x00\x00\x00\x01";$line = $str;$data = str_split($line);foreach($data as $v){  echo dechex(ord($v))."\t";}
得到
fa 1 1 ff aa aa 0 1 0 0 0 0 0 1 

没看出有什么差别

完全模拟你的现场和代码

PHP code

$str="\xFA\x01\x01\xFF\xAA\xAA\x00\x01\x00\x00\x00\x00\x00\x01";

$line = $str;
$data = str_split($line);
foreach($data as $v){
  echo dechex(ord($v))."\t";
}

得到
f……



你这个模拟的是发给硬件的数据是正常的,我的需求是:硬件发的数据我用socket接受不正常,通过抓包工具得到的数据是正确的(FA 01 01 FF AA 03 00 01 00 0B 00 00 00 A3),而用socket得到的数据,在dos下是乱码,我通过dechex(ord(得到的数据))转换后是:fa 7 25 2 fa 2 0 9 f6 4 2c 88 fa 1(是错误的),我想得到的是和抓包工具得到的一样的数据(即:FA 01 01 FF AA 03 00 01 00 0B 00 00 00 A3)

你有 $line = trim($input[$i]); 这是接受到的数据吧?
1、去掉 trim,否则传入的数据可能会被截断
2、因为是二进制数据,你 echo base64_encode($input[$i]); 贴出结果

你有 $line = trim($input[$i]); 这是接受到的数据吧?
1、去掉 trim,否则传入的数据可能会被截断
2、因为是二进制数据,你 echo base64_encode($input[$i]); 贴出结果




+gclAvoCAAn2BCyI+gEB+v/6AQH/qqoAAQAAAAAAAfoBAf+qqgABAAAA
这是得到的数据

$s = base64_decode('+gclAvoCAAn2BCyI+gEB+v/6AQH/qqoAAQAAAAAAAfoBAf+qqgABAAAA');print_r(unpack('H*', $s));//或for($i=0; $i<strlen($s); $i++) printf(' %02X', ord($s{$i}));

你有 $line = trim($input[$i]); 这是接受到的数据吧?
1、去掉 trim,否则传入的数据可能会被截断
2、因为是二进制数据,你 echo base64_encode($input[$i]); 贴出结果


下图是通过抓包工具抓取的数据(正确的数据),图中圈住阴影部分的16进制的数据如何转换成箭头所指的数据,以及如何再转回到16进制 

[img=http://bbs.php100.com/attachment/Mon_1208/18_219521_355456b7c8c862b.jpg?93][/img]

你收到的就是二进制数据,要转来转去干什么?

你红线框住的那些,是数据的十六进制表示。
一个字节是8个二进制位,1个十六进制数是4个二进制位
2个十六进制数正好表示一个字节的内容。

我现在用php socket收到的数据是箭头所指的数据(并且放在变量$a中),我现在想将她转换成图中圈中阴影部分的数据(也就是16进制),改如何转换呢?

你收到的就是二进制数据,要转来转去干什么?

你红线框住的那些,是数据的十六进制表示。
一个字节是8个二进制位,1个十六进制数是4个二进制位
2个十六进制数正好表示一个字节的内容。



我现在用php socket收到的数据是箭头所指的数据(并且放在变量$a中),我现在想将她转换成图中圈中阴影部分的数据(也就是16进制),改如何转换呢?

我 #6 不是给你代码了吗?

说的感觉有点乱,不好意思

是否有转义符?

我 #6 不是给你代码了吗?



现在的确是可以获取到代码了,但是少了3个16进制的数据

获取到的代码是:fa072502fa020009f6042c88fa0101fafffa0101ffaa030001000b00

抓包得到的是:FA 01 01 FF AA 03 00 01 00 0B 00 00 00 A3

也就是少了 00 00 A3

<?php        $sendStr = '30 32 30 34 03 30 33';  // 16进制数据        $sendStrArray = str_split(str_replace(' ', '', $sendStr), 2);  // 将16进制数据转换成两个一组的数组        $socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname("tcp"));  // 创建Socket        if (socket_connect($socket, "192.168.1.100", 8080)) {  //连接            for ($j = 0; $j < count($sendStrArray); $j++) {                socket_write($socket, chr(hexdec($sendStrArray[$j])));  // 逐组数据发送            }            $receiveStr = "";            $receiveStr = socket_read($socket, 1024, PHP_BINARY_READ);  // 采用2进制方式接收数据            $receiveStrHex = bin2hex($receiveStr);  // 将2进制数据转换成16进制            echo "client:" . $receiveStrHex;        }        socket_close($socket);  // 关闭Socket        ?>

可以完美解决你的问题。。。。。。刚看见这个你的问题

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:SQL 查询问题Next article:php 消息推送(含源码)