使用php创建WebSocket服务

WBOY
Freigeben: 2016-07-25 08:50:47
Original
1793 Leute haben es durchsucht
执行方法:
首先先修改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. <script><li>function link(){<li> var url='ws://192.168.0.200:8000';<li> socket=new WebSocket(url);<li> socket.onopen=function(){log('连接成功')}<li> socket.onmessage=function(msg){log('获得消息:'+msg.data);console.log(msg);}<li> socket.onclose=function(){log('断开连接')}<li>}<li>function dis(){<li> socket.close();<li> socket=null;<li>}<li>function log(var1){<li> $('.log').append(var1+"\r\n");<li>}<li>function send(){<li> socket.send($('#text').attr('value'));<li>}<li>function send2(){<li> var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')})<li> socket.send(json);<li>}<li></script>
复制代码
  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 $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,"\r\n")));
  113. $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
  114. $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
  115. $new_message .= "Upgrade: websocket\r\n";
  116. $new_message .= "Sec-WebSocket-Version: 13\r\n";
  117. $new_message .= "Connection: Upgrade\r\n";
  118. $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
  119. socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));
  120. $this->users[$k]['hand']=true;
  121. return true;
  122. }
  123. function uncode($str){
  124. $mask = array();
  125. $data = '';
  126. $msg = unpack('H*',$str);
  127. $head = substr($msg[1],0,2);
  128. if (hexdec($head小贝) === 8) {
  129. $data = false;
  130. }else if (hexdec($head小贝) === 1){
  131. $mask[] = hexdec(substr($msg[1],4,2));
  132. $mask[] = hexdec(substr($msg[1],6,2));
  133. $mask[] = hexdec(substr($msg[1],8,2));
  134. $mask[] = hexdec(substr($msg[1],10,2));
  135. $s = 12;
  136. $e = strlen($msg[1])-2;
  137. $n = 0;
  138. for ($i=$s; $i $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));
  139. $n++;
  140. }
  141. }
  142. return $data;
  143. }
  144. function code($msg){
  145. $msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), '', $msg);
  146. $frame = array();
  147. $frame[0] = '81';
  148. $len = strlen($msg);
  149. $frame[1] = $len $frame[2] = $this->ord_hex($msg);
  150. $data = implode('',$frame);
  151. return pack("H*", $data);
  152. }
  153. function ord_hex($data) {
  154. $msg = '';
  155. $l = strlen($data);
  156. for ($i= 0; $i $msg .= dechex(ord($data{$i}));
  157. }
  158. return $msg;
  159. }
  160. function idwrite($id,$t){//通过id推送信息
  161. if(!$this->users[$id]['socket']){return false;}//没有这个标示
  162. $t=$this->code($t);
  163. return socket_write($this->users[$id]['socket'],$t,strlen($t));
  164. }
  165. function write($k,$t){//通过标示推送信息
  166. $t=$this->code($t);
  167. return socket_write($k,$t,strlen($t));
  168. }
  169. function eventoutput($type,$event){//事件回调
  170. call_user_func($this->event,$type,$event);
  171. }
  172. function log($t){//控制台输出
  173. if($this->log){
  174. $t=$t."\r\n";
  175. fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));
  176. }
  177. }
  178. }
复制代码


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage