使用php建立WebSocket服務

來源:互聯網
上載者:User
執行方法:
首先先修改server.php與index.html的ip
通過命令列執行 [php路徑]\php.exe "[檔案路徑]\server.php"
然後通過瀏覽器開啟index.html
  1. include 'websocket.class.php';
  2. $config=array(
  3. 'address'=>'192.168.0.200',
  4. 'port'=>'8000',
  5. 'event'=>'WSevent',//回呼函數的函數名
  6. 'log'=>true,
  7. );
  8. $websocket = new websocket($config);
  9. $websocket->run();
  10. function WSevent($type,$event){
  11. global $websocket;
  12. if('in'==$type){
  13. $websocket->log('客戶進入id:'.$event['k']);
  14. }elseif('out'==$type){
  15. $websocket->log('客戶退出id:'.$event['k']);
  16. }elseif('msg'==$type){
  17. $websocket->log($event['k'].'訊息:'.$event['msg']);
  18. roboot($event['sign'],$event['msg']);
  19. }
  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. }
  49. ?>
複製代碼
  1. websocket_TEST
  2. <li>=======websocket======<li>
複製代碼
  1. /*
  2. 建立類websocket($config);
  3. $config結構:
  4. $config=array(
  5. 'address'=>'192.168.0.200',//綁定地址
  6. 'port'=>'8000',//綁定連接埠
  7. 'event'=>'WSevent',//回呼函數的函數名
  8. 'log'=>true,//命令列顯示記錄
  9. );
  10. 回呼函數返回資料格式
  11. function WSevent($type,$event)
  12. $type字串 事件類型有以下三種
  13. in 用戶端進入
  14. out 用戶端斷開
  15. msg 用戶端訊息到達
  16. 均為小寫
  17. $event 數組
  18. $event['k']內建使用者列表的userid;
  19. $event['sign']客戶標示
  20. $event['msg']收到的訊息 $type='msg'時才有該資訊
  21. 方法:
  22. run()運行
  23. search(標示)遍曆取得該標示的id
  24. close(標示)中斷連線
  25. write(標示,資訊)推送資訊
  26. idwrite(id,資訊)推送資訊
  27. 屬性:
  28. $users 客戶列表
  29. 結構:
  30. $users=array(
  31. [使用者id]=>array('socket'=>[標示],'hand'=[是否握手-布爾值]),
  32. [使用者id]=>arr.....
  33. )
  34. */
  35. class websocket{
  36. public $log;
  37. public $event;
  38. public $signets;
  39. public $users;
  40. public $master;
  41. public function __construct($config){
  42. if (substr(php_sapi_name(), 0, 3) !== 'cli') {
  43. die("請通過命令列模式運行!");
  44. }
  45. error_reporting(E_ALL);
  46. set_time_limit(0);
  47. ob_implicit_flush();
  48. $this->event = $config['event'];
  49. $this->log = $config['log'];
  50. $this->master=$this->WebSocket($config['address'], $config['port']);
  51. $this->sockets=array('s'=>$this->master);
  52. }
  53. function WebSocket($address,$port){
  54. $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  55. socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
  56. socket_bind($server, $address, $port);
  57. socket_listen($server);
  58. $this->log('開始監聽: '.$address.' : '.$port);
  59. return $server;
  60. }
  61. function run(){
  62. while(true){
  63. $changes=$this->sockets;
  64. @socket_select($changes,$write=NULL,$except=NULL,NULL);
  65. foreach($changes as $sign){
  66. if($sign==$this->master){
  67. $client=socket_accept($this->master);
  68. $this->sockets[]=$client;
  69. $user = array(
  70. 'socket'=>$client,
  71. 'hand'=>false,
  72. );
  73. $this->users[] = $user;
  74. $k=$this->search($client);
  75. $eventreturn = array('k'=>$k,'sign'=>$sign);
  76. $this->eventoutput('in',$eventreturn);
  77. }else{
  78. $len=socket_recv($sign,$buffer,2048,0);
  79. $k=$this->search($sign);
  80. $user=$this->users[$k];
  81. if($len<7){
  82. $this->close($sign);
  83. $eventreturn = array('k'=>$k,'sign'=>$sign);
  84. $this->eventoutput('out',$eventreturn);
  85. continue;
  86. }
  87. if(!$this->users[$k]['hand']){//沒有握手進行握手
  88. $this->handshake($k,$buffer);
  89. }else{
  90. $buffer = $this->uncode($buffer);
  91. $eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer);
  92. $this->eventoutput('msg',$eventreturn);
  93. }
  94. }
  95. }
  96. }
  97. }
  98. function search($sign){//通過標示遍曆擷取id
  99. foreach ($this->users as $k=>$v){
  100. if($sign==$v['socket'])
  101. return $k;
  102. }
  103. return false;
  104. }
  105. function close($sign){//通過標示中斷連線
  106. $k=array_search($sign, $this->sockets);
  107. socket_close($sign);
  108. unset($this->sockets[$k]);
  109. unset($this->users[$k]);
  110. }
  111. function handshake($k,$buffer){
  112. $buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);
  113. $key = trim(substr($buf,0,strpos($buf,"\r\n")));
  114. $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
  115. $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
  116. $new_message .= "Upgrade: websocket\r\n";
  117. $new_message .= "Sec-WebSocket-Version: 13\r\n";
  118. $new_message .= "Connection: Upgrade\r\n";
  119. $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
  120. socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));
  121. $this->users[$k]['hand']=true;
  122. return true;
  123. }
  124. function uncode($str){
  125. $mask = array();
  126. $data = '';
  127. $msg = unpack('H*',$str);
  128. $head = substr($msg[1],0,2);
  129. if (hexdec($head小貝) === 8) {
  130. $data = false;
  131. }else if (hexdec($head小貝) === 1){
  132. $mask[] = hexdec(substr($msg[1],4,2));
  133. $mask[] = hexdec(substr($msg[1],6,2));
  134. $mask[] = hexdec(substr($msg[1],8,2));
  135. $mask[] = hexdec(substr($msg[1],10,2));
  136. $s = 12;
  137. $e = strlen($msg[1])-2;
  138. $n = 0;
  139. for ($i=$s; $i<= $e; $i+= 2) {
  140. $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));
  141. $n++;
  142. }
  143. }
  144. return $data;
  145. }
  146. function code($msg){
  147. $msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), '', $msg);
  148. $frame = array();
  149. $frame[0] = '81';
  150. $len = strlen($msg);
  151. $frame[1] = $len<16?'0'.dechex($len):dechex($len);
  152. $frame[2] = $this->ord_hex($msg);
  153. $data = implode('',$frame);
  154. return pack("H*", $data);
  155. }
  156. function ord_hex($data) {
  157. $msg = '';
  158. $l = strlen($data);
  159. for ($i= 0; $i<$l; $i++) {
  160. $msg .= dechex(ord($data{$i}));
  161. }
  162. return $msg;
  163. }
  164. function idwrite($id,$t){//通過id推送資訊
  165. if(!$this->users[$id]['socket']){return false;}//沒有這個標示
  166. $t=$this->code($t);
  167. return socket_write($this->users[$id]['socket'],$t,strlen($t));
  168. }
  169. function write($k,$t){//通過標示推送資訊
  170. $t=$this->code($t);
  171. return socket_write($k,$t,strlen($t));
  172. }
  173. function eventoutput($type,$event){//事件回調
  174. call_user_func($this->event,$type,$event);
  175. }
  176. function log($t){//控制台輸出
  177. if($this->log){
  178. $t=$t."\r\n";
  179. fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));
  180. }
  181. }
  182. }
複製代碼
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.