PHP之Socket服务器搭建和测试实例分享

小云云
小云云 原创
2023-03-21 10:10:01 1027浏览

1.socket服务器搭建思路

1) 目的:理解socket服务器工作机制

2) 思路:创建socket -> 把socket加入连接池 -> 处理接收信息 -> 握手动作 -> 发送信息

2.socket服务器代码

注:复制到php文件,直接命令行可以运行,不需要其他支持

特别注意:为了能传输中文_sendMsg做了json_encode()

<?php/** * Socket服务器 * @author wuchangliang 2018/1/17 */class SocketServer{   
 private $sockets; //连接池    private $master;    private $handshake;    /**     
 * @param $address     * @param $port     */    public function run($address, $port)   
  {        //配置错误级别、运行时间、刷新缓冲区        
  echo iconv('UTF-8', 'GBK', "欢迎来到PHP Socket测试服务。 \n");        
  error_reporting(0);        
  set_time_limit(0);       
   ob_implicit_flush();        
   //创建socket        
   $this->master = $this->_connect($address, $port);       
    $this->sockets[] = $this->master;        
    //运行socket        while (true) 
    {            $sockets = $this->sockets;           
     $write = NULL;            $except = NULL;            
     socket_select($sockets, $write, $except, NULL);
      //$write,$except传引用            
      foreach ($sockets as $socket) {                
      if ($socket == $this->master) {                   
       $client = socket_accept($socket);                    
       $this->handshake = false;                    
       if ($client) {                        
       $this->sockets[] = $client; //加入连接池                   
        }                } else {                   
         //接收信息                   
          $bytes = @socket_recv($socket, $buffer, 2048, 0);               
               if ($bytes <= 6) {                       
                $this->_disConnect($socket);                      
                  continue;                   
                   };                  
                     //处理信息              
                           if (!$this->handshake) 
                           {                        
                           $this->_handshake($socket, $buffer);                   
                            } else {                        
              $buffer = $this->_decode($buffer);                       
            $this->_sendMsg($buffer, $socket);                   
        }                }            }        }    }    
 
  /**     * 创建socket连接     * @param $address     * @param $port     * @return resource     */   
                               private function _connect($address, $port)   
 {        //创建socket        
 $master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)        
 or die("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");        
 socket_bind($master, $address, $port)        or die("socket_bind() failed: reason: " . 
 socket_strerror(socket_last_error($master)) . "\n");        socket_listen($master, 5)        
 or die("socket_listen() failed: reason: " . socket_strerror(socket_last_error($master)) . "\n");        
 return $master;    }    /**     * 握手动作     * @param $socket     * @param $buffer     */    
 private function _handshake($socket, $buffer)    {        //握手动作信息       
  $buf = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);       
   $key = trim(substr($buf, 0, strpos($buf, "\r\n")));        
   $new_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));        
   $new_message = "HTTP/1.1 101 Switching Protocols\r\n";       
    $new_message .= "Upgrade: websocket\r\n";        $new_message .= "Sec-WebSocket-Version: 13\r\n";        
    $new_message .= "Connection: Upgrade\r\n";        $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";        //记录握手动作        socket_write($socket, $new_message, strlen($new_message));        $this->handshake = true;    }    /**     * 断开socket连接     * @param $socket     */    private function _disConnect($socket)    {        $index = array_search($socket, $this->sockets);        socket_close($socket);        if ($index >= 0) {            array_splice($this->sockets, $index, 1);        }    }    /**     * 发送信息     * @param $buffer     * @param $client     */    private function _sendMsg($buffer, $client)    
    {        $send_buffer = $this->_frame(json_encode($buffer));        foreach ($this->sockets as $socket) {            if ($socket != $this->master && $socket != $client) { //广播发送(除了自己)                socket_write($socket, $send_buffer, strlen($send_buffer));        
        }        }    }    /**     * 解析数据帧    
     * @param $buffer     * @return null|string     */    private function _decode($buffer)    {        $len = $masks = $data = $decoded = null;    
        $len = ord($buffer[1]) & 127;        if ($len === 126) {            $masks = substr($buffer, 4, 4);           
     $data = substr($buffer, 8);        } else if ($len === 127) {            $masks = substr($buffer, 10, 4);            
    $data = substr($buffer, 14);        } else {            $masks = substr($buffer, 2, 4);            $data = substr($buffer, 6);        }    
        for ($index = 0; $index < strlen($data); $index++) {            $decoded .= $data[$index] ^ $masks[$index % 4];        }     
       return $decoded;    }    /**     * 处理返回帧     * @param $buffer     * @return string     */    private function _frame($buffer)   
     {        $len = strlen($buffer);        if ($len <= 125) {            return "\x81" . chr($len) . $buffer;        } else if ($len <= 65535)
     {            return "\x81" . chr(126) . pack("n", $len) . $buffer;        } else 
    {            return "\x81" . char(127) . pack("xxxxN", $len) . $buffer;        }    }}$sc = new SocketServer();$sc->run('127.0.0.1', 2046);

3.客户端代码

注:直接复制到html,和上面的php文件在同一文件夹即可,特别注意onmessage解析的两层 parse

<!DOCTYPE html><html><head>    <meta charset="utf-8" />    <title>WebSocket Test</title>    <script language="javascript"type="text/javascript">        websocket = new WebSocket('ws://127.0.0.1:2046/');        websocket.onopen = function(evt) {            console.log('connect');            websocket.send('{"data":"您好,世界!"}');        };        websocket.onclose = function(evt) {            console.log('onclose');            console.log(evt);        };        websocket.onmessage = function(evt) {            console.log('onmessage');            if (evt.data) {                console.log(JSON.parse(JSON.parse(evt.data)));            }        };        websocket.onerror = function(evt) {            console.log('onerror');            console.log(evt);        };        function sendMsg(){            var sendData = { 'data': document.getElementById('name').value};            websocket.send(JSON.stringify(sendData));        }    </script></head><body>    <h2>WebSocket Test</h2>    <input type="text" name="name" id="name" />    <a href="javascript:;" onclick="sendMsg()">点击发送</a></body></html>

4.测试示例


相关推荐:

PHP中Socket简单使用方法

PHP中Socket服务器搭建和测试方法教程

详解php实现socket推送技术

以上就是PHP之Socket服务器搭建和测试实例分享的详细内容,更多请关注php中文网其它相关文章!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。