首頁 >後端開發 >php教程 >使用php建立WebSocket服務

使用php建立WebSocket服務

WBOY
WBOY原創
2016-07-25 08:50:471835瀏覽
執行方法:
先修改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 @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<li> <li> <li><textarea class="log" style="width: 100%; height: 500px;"><li>======= websocket======</li> <li></textarea></li> <li> <input type="button" value="連接" onclick="link()"> </li> <li><input type="button" value="斷開" onclick="dis()"></li> <li><input type="text" id="text"></li> <li> <input type="button" value="發送" onclick="send()"> </li> <li><script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script></li> <li> <li>function link(){</li> <li> var url='ws://192.168.0.200:8000';</li> <li> socket=new WebSocket(url);</li> <li> socket.openon=function(){ log('連線成功')}</li> <li> socket.onmessage=function(msg){log('取得訊息:' msg.data);console.log(msg);}</li> <li> socket.onclose=function() {log('斷開連接')}</li> <li>}</li> <li>function dis(){</li> <li> socket.close();</li> <li> socket=null;</li> <li>}</li> <li>function log(var1) {</li> <li> $('.log').append(var1 "rn");</li> <li>}</li> <li>function send(){</li> <li> socket.send($('#text').attr(' value'));</li> <li>}</li> <li>function send2(){</li> <li> var json = JSON.stringify({'type':'php','msg':$('#text2').attr( 'value')})</li> <li> socket.send(json);</li> <li>}</li> <li> <li> <li>
複製程式碼
  1. /*
  2. 建立類別websocket($config);
  3. $config結構:
  4. $config=array( ' address'=>'192.168.0.200',//綁定位址
  5. 'port'=>'8000',//綁定連接埠
  6. 'event'=>'WSevent',///回呼函數的函數名
  7. 'log'=>true,//命令列顯示記錄
  8. );
  9. 回呼函數回傳資料格式
  10. function WSevent($type,$event)
  11. $type字串事件類型有以下三種
  12. in 用戶端進入
  13. out 用戶端斷開
  14. msg 用戶端訊息到達
  15. 皆為小寫
  16. $event 陣列
  17. $event['k']內建使用者清單的userid;
  18. $event['sign']客戶標示
  19. $event['msg']收到的訊息$type='msg'時才有此資訊
  20. 方法:
  21. run()運作
  22. search(標示)遍歷取得此標示的id
  23. close(標示)斷開連線
  24. write(推送標示,訊息)訊息
  25. idwrite(id,訊息)推播訊息
  26. 屬性:
  27. $users 客戶清單
  28. 結構:
  29. $users=array(
  30. [使用者id]=>array ('socket'=>[標示],'hand'=[是否握手-布林值]),
  31. [使用者id]=>arr.....
  32. )
  33. */
  34. class websocket{
  35. public $log;
  36. public $event;
  37. public $signets;
  38. public $users;
  39. public $master;
  40. public function __construct($configtion __construct($config ){
  41. if (substr(php_sapi_name(), 0, 3) !== 'cli') {
  42. die("請透過命令列模式執行!");
  43. }
  44. error_reporting( E_ALL);
  45. set_time_limit(0);
  46. ob_implicit_flush();
  47. $this->event = $config['event'];
  48. $this->log = $config['log' ];
  49. $this->master=$this->WebSocket($config['address'], $config['port']);
  50. $this->sockets=array('s'=> $this->master);
  51. }
  52. function WebSocket($address,$port){
  53. $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  54. socket_set_option(SOCA), SOL_TCP);
  55. socket_set_option($D), SOL_SOCS. , 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 $ this->close($sign);
  82. $eventreturn = array('k'=>$k,'sign'=>$sign);
  83. $this->eventoutput('out',$eventreturn) ;
  84. continue;
  85. }
  86. if(!$this->users[$k]['hand']){//沒有握手握手
  87. $this->handshake($k, $buffer);
  88. }else{
  89. $buffer = $this->uncode($buffer);
  90. $eventreturn = array('k'=>$k,'sign'=>$sign, 'msg'=>$buffer);
  91. $this->eventoutput('msg',$eventreturn);
  92. }
  93. }
  94. }
  95. }
  96. }
  97. function search($sign){//透過標示遍歷取得id
  98. foreach ($this->users as $k=>$v){
  99. if($sign==$v['socket'])
  100. return $k;
  101. }
  102. return false;
  103. }
  104. function close($sign){//透過標示斷開連接
  105. $k=array_search($sign, $this ->sockets);
  106. socket_close($sign);
  107. unset($this->sockets[$k]);
  108. unset($this->users[$k]);
  109. }
  110. function handshake($k,$buffer){
  111. $buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:') 18);
  112. $key = trim(substr ($buf,0,strpos($buf,"rn")));
  113. $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
  114. $new_message = "HTTP/1.1 101 Switching Protocolsrn";
  115. $new_message .= "Upgrade: websocketrn";
  116. $new_message .= "Sec-WebSocket-Version: 1🎜> $new_message .= "Sec-WebSocket-Version: 1🎜> $new_message .= "Sec-WebSocket-Version: 1🎜> $new_message .= "Sec-WebSocket-Version: 133"; $new_message .= "Sec-WebSocket-Accept: " . $new_key . "rnrn";
  117. socket_write($this->users[$k]['socket'],$new_message ,strlen($new_message));
  118. $this->users[$k]['hand']=true;
  119. return true;
  120. }
  121. function uncode($str){
  122. $mask = array();
  123. $data = '';
  124. $msg = unpack('H*',$str);
  125. $head = substr($msg[1],0,2);
  126. if (hexdec($head小貝) === 8) {
  127. $data = false;
  128. }else if (hexdec($head小貝) === 1){
  129. $mask[] = hexdec(substr($msg[1],4,2));
  130. $mask[ ] = hexdec(substr($msg[1],6,2));
  131. $mask[] = hexdec(substr($msg[1],8,2));
  132. $mask[] = hexdec(substr($msg[1],10,2));
  133. $s = 12;
  134. $e = strlen($msg[1])-2;
  135. $n = 0;
  136. for ($i=$s; $i $data .= chr($mask[$n%4]^hexdec(substr($msg[1 ) ) ],$i,2)));
  137. $n ;
  138. }
  139. }
  140. return $data;
  141. }
  142. 函數碼($msg){
  143. $msg = preg_replace(array('/r$/','/n$ ) /','/rn$/',), '', $msg);
  144. $frame = array();
  145. $frame[0] = '81';
  146. $len = strlen($msg);
  147. $frame[1] = $len $frame[2] = $this->ord_hex($msg);
  148. $data = implode('',$frame);
  149. return pack("H*", $data);
  150. }
  151. function ord_hex($data) {
  152. $msg = '';
  153. $l = strlen($data);
  154. for ($i= 0; $i $msg .= dechex(ord($data{$i}));
  155. }
  156. 回傳 $msg;
  157. }
  158. function idwrite($id,$t){//透過id主體資訊
  159. if(!$this->users[$id]['socket']){return false ;}//沒有這個標記
  160. $t=$this->code($t);
  161. return socket_write($this->users[$id]['socket'],$t, strlen($ t));
  162. }
  163. function write($k,$t){//透過標註主體資訊
  164. $t=$this->code($t);
  165. return socket_write($ k,$t,strlen($t));
  166. }
  167. function eventoutput($type,$event){//事件回呼
  168. call_user_func($this->event,$ type,$event) ;
  169. }
  170. function log($t){// 控制台輸出
  171. if($this->log){
  172. $t=$t."rn" ;
  173. fwrite( 。 >
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn