>백엔드 개발 >PHP 튜토리얼 >PHP 소켓 서버 구축 및 테스트 사례 공유

PHP 소켓 서버 구축 및 테스트 사례 공유

小云云
小云云원래의
2018-03-13 13:20:451664검색

1. 소켓 서버 구축 아이디어

1) 목적: 소켓 서버의 작동 메커니즘 이해

2) 아이디어: 소켓 생성 -> 수신된 정보 -> 핸드셰이크 동작 - > 메시지 보내기

2.socket 서버 코드

참고: PHP 파일에 복사하고 명령줄에서 직접 실행하세요. 다른 지원은 필요하지 않습니다

참고: Chinese_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(&#39;UTF-8&#39;, &#39;GBK&#39;, "欢迎来到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, &#39;Sec-WebSocket-Key:&#39;) + 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(&#39;127.0.0.1&#39;, 2046);

3. 클라이언트 코드

참고: 위의 PHP 파일과 동일한 폴더에 html로 직접 복사하십시오. onmessage

<!DOCTYPE html><html><head>    <meta charset="utf-8" />    <title>WebSocket Test</title>    <script language="javascript"type="text/javascript">        websocket = new WebSocket(&#39;ws://127.0.0.1:2046/&#39;);        websocket.onopen = function(evt) {            console.log(&#39;connect&#39;);            websocket.send(&#39;{"data":"您好,世界!"}&#39;);        };        websocket.onclose = function(evt) {            console.log(&#39;onclose&#39;);            console.log(evt);        };        websocket.onmessage = function(evt) {            console.log(&#39;onmessage&#39;);            if (evt.data) {                console.log(JSON.parse(JSON.parse(evt.data)));            }        };        websocket.onerror = function(evt) {            console.log(&#39;onerror&#39;);            console.log(evt);        };        function sendMsg(){            var sendData = { &#39;data&#39;: document.getElementById(&#39;name&#39;).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에서 소켓을 사용하는 간단한 방법

PHP에서 소켓 서버 설정 및 테스트에 대한 자습서

소켓 푸시 기술의 PHP 구현에 대한 자세한 설명

위 내용은 PHP 소켓 서버 구축 및 테스트 사례 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.