当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP实现websocket通信的方法示例

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-27 14:46:49 浏览: 评论:0 

这篇文章主要介绍了PHP实现websocket通信的方法,结合实例形式分析了php基于websocket类的socket通信相关客户端与服务器端操作技巧,需要的朋友可以参考下

本文实例讲述了PHP实现websocket通信的方法,分享给大家供大家参考,具体如下:

执行方法:

首先先修改server.php与index.html的ip

通过命令行执行 [php路径]\php.exe "[文件路径]\server.php"

然后通过浏览器打开index.html

server.php

  1. <?php 
  2. include 'websocket.class.php'
  3. $config=array
  4.  'address'=>'192.168.0.200'
  5.  'port'=>'8000'
  6.  'event'=>'WSevent',//回调函数的函数名 
  7.  'log'=>true, 
  8. ); 
  9. $websocket = new websocket($config); 
  10. $websocket->run(); 
  11. function WSevent($type,$event){ 
  12.  global $websocket
  13.   if('in'==$type){ 
  14.    $websocket->log('客户进入id:'.$event['k']); 
  15.   }elseif('out'==$type){ 
  16.    $websocket->log('客户退出id:'.$event['k']); 
  17.   }elseif('msg'==$type){ 
  18.    $websocket->log($event['k'].'消息:'.$event['msg']); 
  19.    roboot($event['sign'],$event['msg']); 
  20.   } 
  21. function roboot($sign,$t){ 
  22.  global $websocket
  23.  switch ($t
  24.  { 
  25.  case 'hello'
  26.   $show='hello,GIt @ OSC'
  27.   break
  28.  case 'name'
  29.   $show='Robot'
  30.   break
  31.  case 'time'
  32.   $show='当前时间:'.date('Y-m-d H:i:s'); 
  33.   break
  34.  case '再见'
  35.   $show='( ^_^ )/~~拜拜'
  36.   $websocket->write($sign,'Robot:'.$show); 
  37.   $websocket->close($sign); 
  38.   return
  39.   break
  40.  case '天王盖地虎'
  41.   $array = array('小鸡炖蘑菇','宝塔震河妖','粒粒皆辛苦'); 
  42.   $show = $array[rand(0,2)]; 
  43.   break
  44.  default
  45.   $show='( ⊙o⊙?)不懂,你可以尝试说:hello,name,time,再见,天王盖地虎.'
  46.  } 
  47.  $websocket->write($sign,'Robot:'.$show); 
  48. ?> 

index.html

  1. <!doctype html> 
  2. <html> 
  3. <head> 
  4. <meta charset="utf-8"
  5. <title>websocket_TEST</title> 
  6. </head> 
  7. <body> 
  8. <textarea class="log" style="width: 100%; height: 500px;"
  9. =======websocket====== 
  10. </textarea> 
  11. <input type="button" value="连接" onClick="link()"
  12. <input type="button" value="断开" onClick="dis()"
  13. <input type="text" id="text"
  14. <input type="button" value="发送" onClick="send()"
  15. <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> 
  16. <script> 
  17. function link(){ 
  18.  var url='ws://192.168.0.200:8000'
  19.  socket=new WebSocket(url); 
  20.  socket.onopen=function(){log('连接成功')} 
  21.  socket.onmessage=function(msg){log('获得消息:'+msg.data);console.log(msg);} 
  22.  socket.onclose=function(){log('断开连接')} 
  23. function dis(){ 
  24.  socket.close(); 
  25.  socket=null; 
  26. function log(var1){ 
  27.  $('.log').append(var1+"\r\n"); 
  28. function send(){ 
  29.  socket.send($('#text').attr('value')); 
  30. function send2(){ 
  31.  var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')}) 
  32.  socket.send(json); 
  33. </script> 
  34. </body> 
  35. </html> 

websocket.class.php

  1. <?php 
  2. /* 
  3. 创建类websocket($config); 
  4. $config结构: 
  5. $config=array( 
  6.  'address'=>'192.168.0.200',//绑定地址 
  7.  'port'=>'8000',//绑定端口 
  8.  'event'=>'WSevent',//回调函数的函数名 
  9.  'log'=>true,//命令行显示记录 
  10. ); 
  11. 回调函数返回数据格式 
  12. function WSevent($type,$event) 
  13. $type字符串 事件类型有以下三种 
  14. in 客户端进入 
  15. out 客户端断开 
  16. msg 客户端消息到达 
  17. 均为小写 
  18. $event 数组 
  19. $event['k']内置用户列表的userid; 
  20. $event['sign']客户标示 
  21. $event['msg']收到的消息 $type='msg'时才有该信息 
  22. 方法: 
  23. run()运行 
  24. search(标示)遍历取得该标示的id 
  25. close(标示)断开连接 
  26. write(标示,信息)推送信息 
  27. idwrite(id,信息)推送信息 
  28. 属性: 
  29. $users 客户列表 
  30. 结构: 
  31. $users=array( 
  32. [用户id]=>array('socket'=>[标示],'hand'=[是否握手-布尔值]), 
  33. [用户id]=>arr..... 
  34. ) 
  35. */ 
  36. class websocket{ 
  37.   public $log
  38.   public $event
  39.   public $signets
  40.   public $users
  41.   public $master
  42.   public function __construct($config){ 
  43.     if (substr(php_sapi_name(), 0, 3) !== 'cli') { 
  44.       die("请通过命令行模式运行!"); 
  45.     } 
  46.     error_reporting(E_ALL); 
  47.     set_time_limit(0); 
  48.     ob_implicit_flush(); 
  49.     $this->event = $config['event']; 
  50.     $this->log = $config['log']; 
  51.     $this->master=$this->WebSocket($config['address'], $config['port']); 
  52.     $this->sockets=array('s'=>$this->master); 
  53.   } 
  54.   function WebSocket($address,$port){ 
  55.     $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
  56.     socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1); 
  57.     socket_bind($server$address$port); 
  58.     socket_listen($server); 
  59.     $this->log('开始监听: '.$address.' : '.$port); 
  60.     return $server
  61.   } 
  62.  function run(){ 
  63.   while(true){ 
  64.    $changes=$this->sockets; 
  65.    @socket_select($changes,$write=NULL,$except=NULL,NULL); 
  66.    foreach($changes as $sign){ 
  67.     if($sign==$this->master){ 
  68.      $client=socket_accept($this->master); 
  69.      $this->sockets[]=$client
  70.      $user = array
  71.       'socket'=>$client
  72.       'hand'=>false, 
  73.      ); 
  74.      $this->users[] = $user
  75.      $k=$this->search($client); 
  76.      $eventreturn = array('k'=>$k,'sign'=>$sign); 
  77.      $this->eventoutput('in',$eventreturn); 
  78.     }else
  79.      $len=socket_recv($sign,$buffer,2048,0); 
  80.      $k=$this->search($sign); 
  81.      $user=$this->users[$k]; 
  82.      if($len<7){ 
  83.       $this->close($sign); 
  84.       $eventreturn = array('k'=>$k,'sign'=>$sign); 
  85.       $this->eventoutput('out',$eventreturn); 
  86.       continue
  87.      } 
  88.      if(!$this->users[$k]['hand']){//没有握手进行握手 
  89.       $this->handshake($k,$buffer); 
  90.      }else
  91.       $buffer = $this->uncode($buffer); 
  92.       $eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer); 
  93.       $this->eventoutput('msg',$eventreturn); 
  94.      } 
  95.     } 
  96.    } 
  97.   } 
  98.  } 
  99.  function search($sign){//通过标示遍历获取id 
  100.   foreach ($this->users as $k=>$v){ 
  101.    if($sign==$v['socket']) 
  102.    return $k
  103.   } 
  104.   return false; 
  105.  } 
  106.  function close($sign){//通过标示断开连接 
  107.   $k=array_search($sign$this->sockets); 
  108.   socket_close($sign); 
  109.   unset($this->sockets[$k]); 
  110.   unset($this->users[$k]); 
  111.  } 
  112.  function handshake($k,$buffer){ 
  113.   $buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18); 
  114.   $key = trim(substr($buf,0,strpos($buf,"\r\n"))); 
  115.   $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true)); 
  116.   $new_message = "HTTP/1.1 101 Switching Protocols\r\n"
  117.   $new_message .= "Upgrade: websocket\r\n"
  118.   $new_message .= "Sec-WebSocket-Version: 13\r\n"
  119.   $new_message .= "Connection: Upgrade\r\n"
  120.   $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n"
  121.   socket_write($this->users[$k]['socket'],$new_message,strlen($new_message)); 
  122.   $this->users[$k]['hand']=true; 
  123.   return true; 
  124.  } 
  125.  function uncode($str){ 
  126.   $mask = array(); 
  127.   $data = ''
  128.   $msg = unpack('H*',$str); 
  129.   $head = substr($msg[1],0,2); 
  130.   if (hexdec($head{1}) === 8) { 
  131.    $data = false; 
  132.   }else if (hexdec($head{1}) === 1){ 
  133.    $mask[] = hexdec(substr($msg[1],4,2)); 
  134.    $mask[] = hexdec(substr($msg[1],6,2)); 
  135.    $mask[] = hexdec(substr($msg[1],8,2)); 
  136.    $mask[] = hexdec(substr($msg[1],10,2)); 
  137.    $s = 12; 
  138.    $e = strlen($msg[1])-2; 
  139.    $n = 0; 
  140.    for ($i=$s$i<= $e$i+= 2) { 
  141.     $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2))); 
  142.     $n++; 
  143.    } 
  144.   } 
  145.   return $data
  146.  } 
  147.   function code($msg){ 
  148.    $msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), ''$msg); 
  149.    $frame = array(); 
  150.    $frame[0] = '81'
  151.    $len = strlen($msg); 
  152.    $frame[1] = $len<16?'0'.dechex($len):dechex($len); 
  153.    $frame[2] = $this->ord_hex($msg); 
  154.    $data = implode('',$frame); 
  155.    return pack("H*"$data); 
  156.   } 
  157.   function ord_hex($data) { 
  158.    $msg = ''
  159.    $l = strlen($data); 
  160.    for ($i= 0; $i<$l$i++) { 
  161.     $msg .= dechex(ord($data{$i})); 
  162.    } 
  163.    return $msg
  164.   } 
  165.   function idwrite($id,$t){//通过id推送信息 
  166.    if(!$this->users[$id]['socket']){return false;}//没有这个标示 
  167.    $t=$this->code($t); 
  168.    return socket_write($this->users[$id]['socket'],$t,strlen($t)); 
  169.   } 
  170.   function write($k,$t){//通过标示推送信息 
  171.    $t=$this->code($t); 
  172.    return socket_write($k,$t,strlen($t)); 
  173.   } 
  174.   function eventoutput($type,$event){//事件回调 
  175.    call_user_func($this->event,$type,$event); 
  176.   } 
  177.   function log($t){//控制台输出 
  178.    if($this->log){ 
  179.     $t=$t."\r\n"
  180.     fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t)); 
  181.    } 
  182.   } 
  183. }

Tags: websocket通信

分享到: