>  기사  >  php教程  >  웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습

高洛峰
高洛峰원래의
2016-12-22 10:01:101092검색

이 기사의 예에서는 웹소켓을 기반으로 PHP로 간단한 채팅방을 구축하는 방법을 설명합니다. 참고할 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.
1. 서문

회사 게임에 간단한 채팅방이 있다는 것을 알고 나서 알고보니 node+websocket으로 만든 것이었습니다. 간단한 채팅방을 만들어보세요. 그래서 다양한 정보를 수집하고, 문서를 읽고, 사례를 찾아보고, 간단한 채팅방을 직접 작성했습니다.

http 연결은 짧은 연결과 긴 연결로 구분됩니다. 짧은 연결은 일반적으로 ajax를 사용하여 구현할 수 있으며 긴 연결은 웹소켓입니다. 짧은 연결은 비교적 구현이 간단하지만 너무 많은 리소스를 소비합니다. Websocket은 효율적이지만 호환성에 몇 가지 문제가 있습니다. Websocket은 html5의 리소스입니다

2. 프론트엔드

websocket의 프론트엔드 구현은 매우 간단하고 간단합니다

//连接websocket
 
var ws = new WebSocket("ws://127.0.0.1:8000");
 
//成功连接websoc的时候
 
ws.onopen = function(){}
 
//成功获取服务端输出的消息
 
ws.onmessage = function(e){}
 
//连接错误的时候
ws.onerror = function(){}
 
//向服务端发送数据
 
ws.send();

백엔드

웹소켓의 문제점 주로 백그라운드에서

3.1 웹소켓 연결 과정
웹소켓 통신 다이어그램 PHP가 주로 하는 일은 간단한 통신 다이어그램입니다. 암호화 키를 수락하고 반환하여 소켓 워드 생성 및 핸드셰이크 작업을 완료합니다

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습

다음 그림은 웹소켓을 처리하는 서버의 세부 흐름도입니다

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습

3.2 코드 연습

서버에서 수행하는 프로세스는 대략 다음과 같습니다.

소켓 프로세스를 걸어둡니다. 연결 대기

소켓 연결이 있는 후 소켓 배열을 순회

핸드셰이크가 없으면 핸드셰이크 작업을 수행하고 데이터를 받아 구문 분석하고 씁니다. 출력을 위해 버퍼에 넣습니다

다음은 샘플 코드입니다(클래스를 작성했기 때문에 코드가 함수별로 나누어져 있습니다). 글 하단에는 github 주소와 몇 가지 함정이 나와 있습니다.
1. 먼저 소켓을 생성합니다

//建立套接字
    public function createSocket($address,$port)
    {
      //创建一个套接字
      $socket= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
      //设置套接字选项
      socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
      //绑定IP地址和端口
      socket_bind($socket,$address,$port);
      //监听套接字
      socket_listen($socket);
      return $socket;
    }

소켓을 배열에 넣습니다

public function __construct($address,$port)
    {
      //建立套接字
      $this->soc=$this->createSocket($address,$port);
      $this->socs=array($this->soc);
 
    }

3. 프로세스를 정지합니다. 소켓 배열을 순회하면 여기서 주요 작업이 완료됩니다.

public function run(){
      //挂起进程
      while(true){
        $arr=$this->socs;
        $write=$except=NULL;
        //接收套接字数字 监听他们的状态
        socket_select($arr,$write,$except, NULL);
        //遍历套接字数组
        foreach($arr as $k=>$v){
          //如果是新建立的套接字返回一个有效的 套接字资源
          if($this->soc == $v){
            $client=socket_accept($this->soc);
            if($client <0){
              echo "socket_accept() failed";
            }else{
              // array_push($this->socs,$client);
              // unset($this[]);
              //将有效的套接字资源放到套接字数组
              $this->socs[]=$client;
            }
          }else{
            //从已连接的socket接收数据 返回的是从socket中接收的字节数
            $byte=socket_recv($v, $buff,20480, 0);
            //如果接收的字节是0
            if($byte<7)
              continue;
            //判断有没有握手没有握手则进行握手,如果握手了 则进行处理
            if(!$this->hand[(int)$client]){
              //进行握手操作
              $this->hands($client,$buff,$v);
            }else{
              //处理数据操作
              $mess=$this->decodeData($buff);
                //发送数据
              $this->send($mess,$v);
            }
          }
        }
      }
    }

4. 핸드셰이크 프로세스는 Sec-WebSocket-Key에서 웹소켓 콘텐츠를 수신하는 것입니다. 키를 가져와서 암호화 알고리즘을 통해 버퍼에 기록합니다. (자동 확인에서는 처리가 필요하지 않습니다.)

public function hands($client,$buff,$v)
    {
      //提取websocket传的key并进行加密 (这是固定的握手机制获取Sec-WebSocket-Key:里面的key)
      $buf = substr($buff,strpos($buff,&#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($v,$new_message,strlen($new_message));
      // socket_write(socket,$upgrade.chr(0), strlen($upgrade.chr(0)));
      //标记此套接字握手成功
      $this->hand[(int)$client]=true;
    }

5. 클라이언트 데이터 분석(여기서는 암호화하지 않았으니, 필요하시면 직접 암호화하셔도 됩니다)

//解析数据
    public function decodeData($buff)
    {
      //$buff 解析数据帧
      $mask = array();
      $data = &#39;&#39;;
      $msg = unpack(&#39;H*&#39;,$buff); //用unpack函数从二进制将数据解码
      $head = substr($msg[1],0,2);
      if (hexdec($head{1}) === 8) {
        $data = false;
      }else if (hexdec($head{1}) === 1){
        $mask[] = hexdec(substr($msg[1],4,2));
        $mask[] = hexdec(substr($msg[1],6,2));
        $mask[] = hexdec(substr($msg[1],8,2));
        $mask[] = hexdec(substr($msg[1],10,2));
          //遇到的问题 刚连接的时候就发送数据 显示 state connecting
        $s = 12;
        $e = strlen($msg[1])-2;
        $n = 0;
        for ($i=$s; $i<= $e; $i+= 2) {
          $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));
          $n++;
        }
        //发送数据到客户端
          //如果长度大于125 将数据分块
          $block=str_split($data,125);
          $mess=array(
            &#39;mess&#39;=>$block[0],
            );
        return $mess;         
      }

6. 버퍼에 소켓 쓰기

//发送数据
    public function send($mess,$v)
    {
      //遍历套接字数组 成功握手的 进行数据群发
      foreach ($this->socs as $keys => $values) {
        //用系统分配的套接字资源id作为用户昵称
          $mess[&#39;name&#39;]="Tourist&#39;s socket:{$v}";
          $str=json_encode($mess);
          $writes ="\x81".chr(strlen($str)).$str;
          // ob_flush();
          // flush();
          // sleep(3);
          if($this->hand[(int)$values])
            socket_write($values,$writes,strlen($writes));
        }
    }

7. github 주소 git@github.com:rsaLive/websocket.git

① 콘솔에서 server.php를 실행하는 것이 가장 좋습니다

server.php 스크립트 디렉토리로 이동합니다(먼저 php를 할 수 있습니다) -v는 php가 구성되어 있는지 확인합니다. Linux 구성이 없으면 Linux의 bash 창에서 경로를 구성합니다.

php -f server.php

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습오류가 있는 경우

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습하라는 메시지가 표시됩니다. ②서버를 통해 html 파일에 액세스

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습8. 밟힌 함정에 대해서는 디버깅을 열어 오류 보기를 용이하게 합니다.

①멈춘 프로세스에서 server.php를 사용할 수 있습니다. 인쇄된 출력물에 문제가 있으면 추가할 수 있습니다. 디버깅을 위해 코드에 인쇄

각 판단을 표시하고 코드가 실행 중인 섹션을 콘솔에서 확인할 수 있습니다.

하지만 코드를 수정할 때마다 php 스크립트를 다시 실행해야 합니다. server.php

② 이 오류가 발생하면

웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습일 수 있습니다. 1. 서버와 소켓 초기화 시 데이터를 보냅니다. (그 동안에는 콘텐츠를 보낼 수 없습니다.) 서버와의 첫 번째 확인 핸드셰이크)

2. 메시지가 확인되었지만 클라이언트가 메시지를 보내지 않았거나 보낸 메시지가 비어 있는 경우에도 마찬가지입니다.

그러므로 메시지의 데이터를 확인하세요. 연결된 소켓

③可能浏览器不支持或者服务端没有开启socket开始之前最好验证下

if (window.WebSocket){
  console.log("This browser supports WebSocket!");
} else {
  console.log("This browser does not support WebSocket.");
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多웹소켓을 기반으로 간단한 채팅방을 구축하는 PHP 실습相关文章请关注PHP中文网!

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