吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4035|回复: 5
收起左侧

[其他转载] PHPwebsocket协议分析

[复制链接]
1327067592 发表于 2018-11-26 20:33
PHPwebsocket协议分析
phpwebsocket客户端,
首先这个协议我也是最近才接触的,找了一堆资料什么

我觉得有很多资料很是误导新手学习, 说什么是http协议,发送一个协议,表示要升级为
websocket协议,这么说新手根本搞不懂。

其实就是tcp协议,先连接服务器,在发送一个 http 的协议头 然后服务器接收后,返回101 和秘钥, 然后就算握手成功,

即可互相发送消息。

下面附上我写的代码



<?php
/*

  • websocket
  • */

$id['host']="127.0.0.1"; $id['port']=29015;
$rcon=new Rcon($id);

class Rcon
{
private $_Socket = null; private$_buffer = '';
/**csw |

  • @var int
    */
    private $_perLength = 10; public function __construct($param,$isBlock=1) { //连接服务器 当你new这个类时,就会自动连接服务器 $this->_connect($param['host'],$param['port'],$isBlock);

    }
    public function index()
    {
    sleep(5);
    for($i=1;$i<=20;$i++) { $pid = pcntl_fork();
    if($pid) { } else { $this->sendData($i.'#'); exit(); } } } public function sendData($data)
    {
    return fwrite($this-&gt;_Socket,$this->encode($data)) or die('Error:'); } private function encode($data ) {
    $data = is_array($data ) || is_object( $data ) ? json_encode($data ) : (string) $data; $len = strlen( $data ); $mask=array();
    for ($j=0;$j<4;$j++) { $mask[]=mt_rand(1,255);
    }
    $head[0] = 129; if ($len <= 125 ) {
    $head[1] =$len;
    } elseif ( $len &lt;= 65535 ) { $split = str_split( sprintf('%016b', $len ), 8 ); $head[1] = 126;
    $head[2] = bindec($split[0] );
    $head[3] = bindec($split[1] );
    } else {
    $split = str_split( sprintf('%064b',$len ), 8 );
    $head[1] = 127; for ($i = 0; $i &lt; 8;$i++ ) {
    $head[$i+2] = bindec( $split[$i] );
    }
    if ( $head[2] &gt; 127 ) { return false; } } $head[1]+=128;
    $head=array_merge($head,$mask); foreach($head as $k =&gt;$v ) {
    $head[$k] = chr( $v ); } $mask_data='';
    for ($j=0;$j<$len;$j++) {
    $mask_data.=chr(ord($data[$j]) ^$mask[$j % 4]); } return implode('',$head ) . $mask_data; } private function _connect($host, $port,$isBlock=1)
    {

    $key1 = $this->_generateRandomString(32);
    $key2 = $this->_generateRandomString(32);
    $key3 = $this->_generateRandomString(8, false, true);
    $header = "GET ws://".$host.":".$port."/ HTTP/1.1\r\n";
    $header.= "Host: ".$host.":".$port."\r\n";
    $header.= "Connection: Upgrade\r\n";
    $header.= "Pragma: no-cache\r\n";
    $header.= "Cache-Control: no-cache\r\n";
    $header.= "Upgrade: websocket\r\n";
    $header.= "Sec-WebSocket-Version: 13\r\n";
    $header.= "User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36\r\n";
    $header.= "Accept-Encoding: gzip, deflate, sdch\r\n";
    $header.= "Accept-Language: zh-CN,zh;q=0.8\r\n";
    $header.= "Sec-WebSocket-Key: " . $key1 . "\r\n";
    $header.= "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n";
    $header.= "\r\n";
    $this->_Socket = fsockopen($host, $port, $errno, $errstr, 2);
    if(!$isBlock)
        stream_set_blocking  ($this->_Socket,0);
    fwrite($this->_Socket, $header) or die('Error: ' . $errno . ':' . $errstr);
    do{
        $resHand = fread($this->_Socket,2000);
      echo $resHand;
        if($resHand)
            break;
    }while(true);
    
    return true;

    }
    public function receive()
    {
    $response = fread($this->_Socket,2000);
    $bitArr =$this->strToBit($response); $this->decode($bitArr);
    }

    private function decode($strBit) { if(empty($strBit))
    return ;
    $byte2 =$strBit[1];
    $lengthSign = substr($byte2,1);
    $lengthSign = bindec($lengthSign);
    if($lengthSign &lt;=125) { $dataLength = $lengthSign; $packageLength = $dataLength + 2; $data = array_slice($strBit,2,$dataLength);
    $next = array_slice($strBit,2+$dataLength); } elseif($lengthSign == 126)
    {
    $byte3 =$strBit[2];
    $byte4 =$strBit[3];
    $dataLength = bindec($byte3.$byte4); $packageLength = $dataLength + 4; $data = array_slice($strBit,4,$dataLength);
    $next = array_slice($strBit,4+$dataLength); } elseif($lengthSign == 127)
    {
    $byte3 =$strBit[2];
    $byte4 =$strBit[3];
    $byte5 =$strBit[4];
    $byte6 =$strBit[5];
    $dataLength = bindec($byte3.$byte4.$byte5.$byte6); $packageLength = $dataLength + 8; $data  = array_slice($strBit,6,$dataLength);
    $next = array_slice($strBit,6+$dataLength); } $temp='';
    foreach ($data as$key=>$val) { $temp.= chr(bindec($val)); } $this->_buffer[] = array(
    'length' => $dataLength, 'data' =&gt;$temp,
    );
    if(!empty($next)) { $this->decode($next);
    }
    }
    /**csw

  • */
    private function getLength($strBit) { if(empty($strBit))
    return ;
    $byte2 =$strBit[1];
    $lengthSign = substr($byte2,1);
    $lengthSign = bindec($lengthSign);
    $dataLength = 0; $packageLength = 0;
    if($lengthSign &lt;=125) { $dataLength = $lengthSign; $packageLength = $dataLength + 2; } elseif($lengthSign == 126)
    {
    $byte3 =$strBit[2];
    $byte4 =$strBit[3];
    $dataLength = bindec($byte3.$byte4); $packageLength = $dataLength + 4; } elseif($lengthSign == 127)
    {
    $byte3 =$strBit[2];
    $byte4 =$strBit[3];
    $byte5 =$strBit[4];
    $byte6 =$strBit[5];
    $dataLength = bindec($byte3.$byte4.$byte5.$byte6); $packageLength = $dataLength + 8; } $res = array(
    'dataLength' => $dataLength, 'packageLength' =&gt;$packageLength,
    );
    return $res;
    }
    /**csw

  • 闂佸吋鍎抽崲鑼躲亹閸ャ劎鈻旈柨鐔诲Г缁嬪顢旈崟顐ゆ▉闂備焦褰冮惉鐓庘枔閹达箑鏋侀柣妤�鐗嗙粊锟�
    */
    public function getOnePackage()
    {
    $response = fread($this->_Socket,$this-&gt;_perLength); if(!$response)
    return false;
    $bitArr =$this->strToBit($response); $responseLength = strlen($response); $length = $this-&gt;getLength($bitArr);
    $dataLength =$length['dataLength'];
    $packageLength =$length['packageLength'];
    $protocolLength =$packageLength - $dataLength; $realData = '';
    if($packageLength &lt;=$responseLength)
    {
    $dataArr = array_slice($bitArr,$protocolLength,$dataLength);
    $realData =$this->getRealData($dataArr); } else { $dataArr = array_slice($bitArr,$protocolLength);
    $realData =$this->getRealData($dataArr); do { $needLength = $dataLength - strlen($realData);
    $response = fread($this->_Socket,$needLength); $responseLength = strlen($response); $realData.= $response; }while($needLength > $responseLength); } $res = array(
    'packageLength' => $packageLength, 'dataLength' =&gt;$dataLength,
    'data'  => $realData, ); return$res;
    }
    private function getRealData($dataArr) { $temp = '';
    foreach ($dataArr as$key=>$val) { $temp.=chr(bindec($val)); } return$temp;
    }

    private function strToBit($str,$isArr=true)
    {
    $byteLength = strlen($str);
    $byteArr = array(); for($i=0;$i&lt;$byteLength;$i++) { $byteArr[] = str_pad(decbin(ord($str[$i])),8,'0',STR_PAD_LEFT);
    }
    if($isArr) return$byteArr;
    $byteStr = implode('',$byteArr);
    return $byteStr; } private function _generateRandomString($length = 10, $addSpaces = true,$addNumbers = true)
    {
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"闁圭》鎷&#65533;$%&/()=[]{}';
    $useChars = array(); // select some random chars: for($i = 0; $i &lt;$length; $i++) { $useChars[] = $characters[mt_rand(0, strlen($characters)-1)];
    }
    // add spaces and numbers:
    if($addSpaces === true) { array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');
    }
    if($addNumbers === true) { array_push($useChars, rand(0,9), rand(0,9), rand(0,9));
    }
    shuffle($useChars); $randomString = trim(implode('', $useChars)); $randomString = substr($randomString, 0,$length);
    return $randomString; } private function _disconnect() { fclose($this->_Socket);
    }
    public function __destruct()
    {
    $this-&gt;_disconnect(); } public function getData() { return$this->_buffer;
    }
    }

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

asd15555866 发表于 2018-11-26 20:50
大佬泥猴  大佬再见
微冷的夏季 发表于 2019-1-16 14:43
风二中 发表于 2019-1-18 00:56
打字的小强 发表于 2019-1-18 09:17
一点注释都没有告辞
头像被屏蔽
大象无形 发表于 2019-3-22 06:47
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 05:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表