找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 56|回复: 0

[文章] websocket范例

[复制链接]

86

主题

84

回帖

728

积分

管理员

积分
728
发表于 2024-5-24 10:26:36 | 显示全部楼层 |阅读模式
  1. <?php

  2. class SocketService
  3. {
  4.     private $address;
  5.     private $port;
  6.     private $_sockets;
  7.     public function __construct($address = '', $port='')
  8.     {
  9.         if(!empty($address)){
  10.             $this->address = $address;
  11.         }
  12.         if(!empty($port)) {
  13.             $this->port = $port;
  14.         }
  15.     }

  16.     public function service(){
  17.         //获取tcp协议号码。
  18.         $tcp = getprotobyname("tcp");
  19.         $sock = socket_create(AF_INET, SOCK_STREAM, $tcp);
  20.         socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
  21.         if($sock < 0)
  22.         {
  23.             throw new Exception("failed to create socket: ".socket_strerror($sock)."\n");
  24.         }
  25.         socket_bind($sock, $this->address, $this->port);
  26.         socket_listen($sock, $this->port);
  27.         echo "listen on $this->address $this->port ... \n";
  28.         $this->_sockets = $sock;
  29.     }

  30.     public function run(){
  31.         $this->service();
  32.         $clients[] = $this->_sockets;
  33.         while (true){
  34.             $changes = $clients;
  35.             $write = NULL;
  36.             $except = NULL;
  37.             socket_select($changes,  $write,  $except, NULL);
  38.             foreach ($changes as $key => $_sock){
  39.                 if($this->_sockets == $_sock){ //判断是不是新接入的socket
  40.                     if(($newClient = socket_accept($_sock))  === false){
  41.                         die('failed to accept socket: '.socket_strerror($_sock)."\n");
  42.                     }
  43.                     $line = trim(socket_read($newClient, 1024));
  44.                     $this->handshaking($newClient, $line);
  45.                     //获取client ip
  46.                     socket_getpeername ($newClient, $ip);
  47.                     $clients[$ip] = $newClient;
  48.                     echo  "Client ip:{$ip}   \n";
  49.                     echo "Client msg:{$line} \n";
  50.                 } else {
  51.                     socket_recv($_sock, $buffer,  2048, 0);
  52.                     $msg = $this->message($buffer);
  53.                     //在这里业务代码
  54.                     echo "{$key} clinet msg:",$msg,"\n";
  55.                     fwrite(STDOUT, 'Please input a argument:');
  56.                     $response = trim(fgets(STDIN));
  57.                     $this->send($_sock, $response);
  58.                     echo "{$key} response to Client:".$response,"\n";
  59.                 }
  60.             }
  61.         }
  62.     }

  63.     /**
  64.      * 握手处理
  65.      * @param $newClient socket
  66.      * @return int  接收到的信息
  67.      */
  68.     public function handshaking($newClient, $line){

  69.         $headers = array();
  70.         $lines = preg_split("/\r\n/", $line);
  71.         foreach($lines as $line)
  72.         {
  73.             $line = chop($line);
  74.             if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
  75.             {
  76.                 $headers[$matches[1]] = $matches[2];
  77.             }
  78.         }
  79.         $secKey = $headers['Sec-WebSocket-Key'];
  80.         $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
  81.         $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
  82.             "Upgrade: websocket\r\n" .
  83.             "Connection: Upgrade\r\n" .
  84.             "WebSocket-Origin: $this->address\r\n" .
  85.             "WebSocket-Location: ws://$this->address:$this->port/websocket/websocket\r\n".
  86.             "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
  87.         return socket_write($newClient, $upgrade, strlen($upgrade));
  88.     }

  89.     /**
  90.      * 解析接收数据
  91.      * @param $buffer
  92.      * @return null|string
  93.      */
  94.     public function message($buffer){
  95.         $len = $masks = $data = $decoded = null;
  96.         $len = ord($buffer[1]) & 127;
  97.         if ($len === 126)  {
  98.             $masks = substr($buffer, 4, 4);
  99.             $data = substr($buffer, 8);
  100.         } else if ($len === 127)  {
  101.             $masks = substr($buffer, 10, 4);
  102.             $data = substr($buffer, 14);
  103.         } else  {
  104.             $masks = substr($buffer, 2, 4);
  105.             $data = substr($buffer, 6);
  106.         }
  107.         for ($index = 0; $index < strlen($data); $index++) {
  108.             $decoded .= $data[$index] ^ $masks[$index % 4];
  109.         }
  110.         return $decoded;
  111.     }

  112.     /**
  113.      * 发送数据
  114.      * @param $newClinet 新接入的socket
  115.      * @param $msg   要发送的数据
  116.      * @return int|string
  117.      */
  118.     public function send($newClinet, $msg){
  119.         $msg = $this->frame($msg);
  120.         socket_write($newClinet, $msg, strlen($msg));
  121.     }

  122.     public function frame($s) {
  123.         $a = str_split($s, 125);
  124.         if (count($a) == 1) {
  125.             return "\x81" . chr(strlen($a[0])) . $a[0];
  126.         }
  127.         $ns = "";
  128.         foreach ($a as $o) {
  129.             $ns .= "\x81" . chr(strlen($o)) . $o;
  130.         }
  131.         return $ns;
  132.     }

  133.     /**
  134.      * 关闭socket
  135.      */
  136.     public function close(){
  137.         return socket_close($this->_sockets);
  138.     }
  139. }

  140. $sock = new SocketService('0.0.0.0','1443');
  141. $sock->run();
复制代码


  1. #客户端


  2. <!doctype html>
  3. <html lang="en">
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
  7.     <title>websocket</title>
  8. </head>
  9. <body>
  10. <input id="text" value="">
  11. <input type="submit" value="send" onclick="start()">
  12. <input type="submit" value="close" onclick="close()">
  13. <div id="msg"></div>
  14. <script>
  15.     /**
  16.      *0:未连接
  17.      *1:连接成功,可通讯
  18.      *2:正在关闭
  19.      *3:连接已关闭或无法打开
  20.      */
  21.         //创建一个webSocket 实例
  22.     var webSocket  = new  WebSocket("ws://127.0.0.1:1443");

  23.     webSocket.onerror = function (event){
  24.         onError(event);
  25.     };

  26.     // 打开websocket
  27.     webSocket.onopen = function (event){
  28.         onOpen(event);
  29.     };

  30.     //监听消息
  31.     webSocket.onmessage = function (event){
  32.         onMessage(event);
  33.     };


  34.     webSocket.onclose = function (event){
  35.         onClose(event);
  36.     }

  37.     //关闭监听websocket
  38.     function onError(event){
  39.         document.getElementById("msg").innerHTML = "<p>close</p>";
  40.         console.log(event);
  41.         console.log("error"+event.data);
  42.     };

  43.     function onOpen(event){
  44.         console.log("open:"+sockState());
  45.         document.getElementById("msg").innerHTML = "<p>Connect to Service</p>";
  46.     };

  47.     function onMessage(event){
  48.         console.log("onMessage");
  49.         document.getElementById("msg").innerHTML += "<p>response:"+event.data+"</p>"
  50.     };

  51.     function onClose(event){
  52.         document.getElementById("msg").innerHTML = "<p>close</p>";
  53.         console.log("close:"+sockState());
  54.         webSocket.close();
  55.     }

  56.     function sockState(){
  57.         var status = ['未连接','连接成功,可通讯','正在关闭','连接已关闭或无法打开'];
  58.         return status[webSocket.readyState];
  59.     }

  60.     function start(event){
  61.         console.log(webSocket);
  62.         var msg = document.getElementById('text').value;
  63.         document.getElementById('text').value = '';
  64.         console.log("send:"+sockState());
  65.         console.log("msg="+msg);
  66.         webSocket.send("msg="+msg);
  67.         document.getElementById("msg").innerHTML += "<p>request"+msg+"</p>"
  68.     };

  69.     function close(event){
  70.         webSocket.close();
  71.     }
  72. </script>
  73. </body>
  74. </html>
复制代码


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Discuz! X

GMT+8, 2025-12-6 13:25 , Processed in 0.100913 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表