php原生websocket

8303 ワード

class websocket
{
    public $log;
    public $event;
    public $signets;
    public $users;
    public $master;
    public $obj;
    public function __construct($config)
    {
        if (substr(php_sapi_name(), 0, 3) !== 'cli') {
            die("          !");
        }
        error_reporting(E_ALL);
        set_time_limit(0);
        ob_implicit_flush();
        $this->event = $config['event'];
        $this->log = $config['log'];
        $this->obj = $config['obj'];
        $this->master = $this->WebSocket($config['address'], $config['port']);
        $this->sockets = array('s' => $this->master);
    }
    function WebSocket($address, $port)
    {
        $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
        socket_bind($server, $address, $port);
        socket_listen($server);
        $this->log('    : ' . $address . ' : ' . $port);
        return $server;
    }
    function run()
    {
        while (true) {
            $changes = $this->sockets;
            @socket_select($changes, $write = NULL, $except = NULL, NULL);
            foreach ($changes as $sign) {
                if ($sign == $this->master) {
                    $client = socket_accept($this->master);
                    $this->sockets[] = $client;
                    $user = array(
                        'socket' => $client,
                        'hand' => false,
                    );
                    $this->users[] = $user;
                    $k = $this->search($client);

                    $eventreturn = array('k' => $k, 'sign' => $sign);
                    $this->eventoutput('in', $eventreturn);
                } else {
                    $len = socket_recv($sign, $buffer, 2048, 0);
                    $k = $this->search($sign);
                    $user = $this->users[$k];
                    if ($len close($sign);
                        $eventreturn = array('k' => $k, 'sign' => $sign);
                        $this->eventoutput('out', $eventreturn);
                        continue;
                    }
                    if (!$this->users[$k]['hand']) {//        
                        $this->handshake($k, $buffer);
                    } else {
                        $buffer = $this->uncode($buffer);
                        $eventreturn = array('k' => $k, 'sign' => $sign, 'msg' => $buffer);
                        $this->eventoutput('msg', $eventreturn);
                    }
                }
            }
        }
    }
    function search($sign)
    {//        id
        foreach ($this->users as $k => $v) {
            if ($sign == $v['socket'])
                return $k;
        }
        return false;
    }
    function close($sign)
    {//        
        $k = array_search($sign, $this->sockets);
        socket_close($sign);
        unset($this->sockets[$k]);
        unset($this->users[$k]);
    }
    function handshake($k, $buffer)
    {
        $buf = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);
        $key = trim(substr($buf, 0, strpos($buf, "\r
")));         $new_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));         $new_message = "HTTP/1.1 101 Switching Protocols\r
";         $new_message .= "Upgrade: websocket\r
";         $new_message .= "Sec-WebSocket-Version: 13\r
";         $new_message .= "Connection: Upgrade\r
";         $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r
\r
";         socket_write($this->users[$k]['socket'], $new_message, strlen($new_message));         $this->users[$k]['hand'] = true;         return true;     }     function uncode($str)     {         $mask = array();         $data = '';         $msg = unpack('H*', $str);         $head = substr($msg[1], 0, 2);         if (hexdec($head{1}) === 8) {             $data = false;         } else if (hexdec($head{1}) === 1) {             $mask[] = hexdec(substr($msg[1], 4, 2));             $mask[] = hexdec(substr($msg[1], 6, 2));             $mask[] = hexdec(substr($msg[1], 8, 2));             $mask[] = hexdec(substr($msg[1], 10, 2));             $s = 12;             $e = strlen($msg[1]) - 2;             $n = 0;             for ($i = $s; $i <= $e; $i += 2) {                 $data .= chr($mask[$n % 4] ^ hexdec(substr($msg[1], $i, 2)));                 $n++;             }         }         return $data;     }     function code($msg)     {         $msg = preg_replace(array('/\r$/', '/
$/', '/\r
$/',), '', $msg);         $frame = array();         $frame[0] = '81';         $len = strlen($msg);         $frame[1] = $len ord_hex($msg);         $data = implode('', $frame);         return pack("H*", $data);     }     function ord_hex($data)     {         $msg = '';         $l = strlen($data);         for ($i = 0; $i users[$id]['socket']) {             return false;         }//         $t = $this->code($t);         return socket_write($this->users[$id]['socket'], $t, strlen($t));     }     function write($k, $t)     {//         $t = $this->code($t);         return socket_write($k, $t, strlen($t));     }     function eventoutput($type, $event)     {//         call_user_func(array($this->obj, $this->event), $this, $type, $event);     }     function log($t)     {//         if ($this->log) {             $t = $t . "\r
";             fwrite(STDOUT, $t);         }     } }

server.php
'192.168.1.12',
  'port'=>'8000',
  'event'=>'WSevent',//        
  'log'=>true,
);
$websocket = new websocket($config);
$websocket->run();
function WSevent($type,$event){
  global $websocket;
    if('in'==$type){
      $websocket->log('    id:'.$event['k']);
    }elseif('out'==$type){
      $websocket->log('    id:'.$event['k']);
    }elseif('msg'==$type){
      $websocket->log($event['k'].'  :'.$event['msg']);
      roboot($event['sign'],$event['msg']);
    }
}
 
function roboot($sign,$t){
  global $websocket;
  switch ($t)
  {
  case 'hello':
    $show='hello,GIt @ OSC';
    break;  
  case 'name':
    $show='Robot';
    break;
  case 'time':
    $show='    :'.date('Y-m-d H:i:s');
    break;
  case '  ':
    $show='( ^_^ )/~~  ';
    $websocket->write($sign,'Robot:'.$show);
    $websocket->close($sign);
    return;
    break;
  case '     ':
    $array = array('     ','     ','     ');
    $show = $array[rand(0,2)];
    break;
  default:
    $show='( ⊙o⊙?)  ,      :hello,name,time,  ,     .';
  }
  $websocket->write($sign,'Robot:'.$show);
}
?>

端末でphp server.php
index.html
html>



websocket_TEST



index2

 





function link(){
  var url='ws://192.168.1.12:8000';
  socket=new WebSocket(url);
  socket.onopen=function(){log('    ')}
  socket.onmessage=function(msg){log('    :'+msg.data);console.log(msg);}
  socket.onclose=function(){log('    ')}
}
function dis(){
  socket.close();
  socket=null;
}
function log(var1){
  $('.log').append(var1+"\r
"); } function send(){   socket.send($('#text').attr('value')); } function send2(){   var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')})   socket.send(json); }

転載先:https://blog.51cto.com/felixcode/1715074