PHP-Praxis zum Erstellen eines einfachen Chatrooms basierend auf dem websocket_php-Beispiel

WBOY
Freigeben: 2023-03-02 22:38:02
Original
1274 Leute haben es durchsucht

Das Beispiel in diesem Artikel beschreibt die Praxis des Aufbaus eines einfachen Chatrooms in PHP basierend auf WebSocket. Teilen Sie es als Referenz mit allen. Die Details lauten wie folgt:
1. Vorwort

Es gibt einen einfachen Chatroom im Firmenspiel. Nachdem ich davon erfahren hatte, wurde mir klar, dass er von node+websocket erstellt wurde. Ich dachte darüber nach, einen einfachen Chatroom zu erstellen. Also habe ich verschiedene Informationen gesammelt, Dokumente gelesen, nach Beispielen gesucht und selbst einen einfachen Chatroom geschrieben.

HTTP-Verbindungen werden in kurze und lange Verbindungen unterteilt. Kurze Verbindungen können im Allgemeinen mit Ajax implementiert werden, lange Verbindungen sind Websockets. Kurze Verbindungen sind relativ einfach zu implementieren, verbrauchen jedoch zu viele Ressourcen. Websocket ist effizient, weist jedoch einige Kompatibilitätsprobleme auf. Websocket ist eine Ressource von HTML5

2. Frontend

Die Front-End-Implementierung von Websocket ist sehr einfach und unkompliziert

//连接websocket

var ws = new WebSocket("ws://127.0.0.1:8000");

//成功连接websoc的时候

ws.onopen = function(){}

//成功获取服务端输出的消息

ws.onmessage = function(e){}

//连接错误的时候
ws.onerror = function(){}

//向服务端发送数据

ws.send();
Nach dem Login kopieren

3. Backstage

Die Schwierigkeit von Websocket liegt hauptsächlich im Hintergrund

3.1Websocket-Verbindungsprozess
Websocket-Kommunikationsdiagramm Dies ist ein einfaches Kommunikationsdiagramm zwischen dem Client und dem Server. PHP akzeptiert hauptsächlich den Verschlüsselungsschlüssel und gibt ihn zurück, um die Socket-Erstellung und den Handshake-Vorgang abzuschließen

Das Bild unten ist ein detailliertes Flussdiagramm des Serververarbeitungs-Websockets

3.2 Code-Praxis

Der vom Server durchgeführte Prozess ist ungefähr wie folgt:

  1. Hängen Sie einen Socket-Prozess an, der auf eine Verbindung wartet
  2. Durchlaufen Sie das Socket-Array, nachdem eine Socket-Verbindung besteht
  3. Wenn es keinen Handshake gibt, wird der Handshake-Vorgang ausgeführt. Wenn es einen Handshake gibt, werden die Daten empfangen, analysiert und zur Ausgabe in den Puffer geschrieben

Das Folgende ist ein Beispielcode (ich habe eine Klasse geschrieben, daher ist der Code nach Funktionen segmentiert. Am Ende des Textes sind die Github-Adresse und einige Fallstricke angegeben, auf die ich gestoßen bin
). 1. Erstellen Sie zunächst den Socket

//建立套接字
    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;
    }
Nach dem Login kopieren

2. Stecken Sie den Sockel in das Array

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

    }

Nach dem Login kopieren

3. Der angehaltene Prozess durchläuft das Socket-Array und die Hauptoperationen werden hier abgeschlossen

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);
            }
          }
        }
      }
    }
Nach dem Login kopieren

4. Der Vorgang besteht darin, den Websocket-Inhalt zu empfangen, den Schlüssel von Sec-WebSocket-Key zu erhalten und ihn über den Verschlüsselungsalgorithmus in den Puffer zu schreiben (für die automatische Überprüfung ist keine Verarbeitung durch uns erforderlich). )

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

5. Analysieren Sie die Client-Daten (ich habe sie hier nicht verschlüsselt, Sie können sie bei Bedarf selbst verschlüsseln)

//解析数据
    public function decodeData($buff)
    {
      //$buff 解析数据帧
      $mask = array(); 
      $data = ''; 
      $msg = unpack('H*',$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(
            'mess'=>$block[0],
            );
        return $mess;          
      }
Nach dem Login kopieren

6. Schreiben Sie den Socket in den Puffer

//发送数据
    public function send($mess,$v)
    {
      //遍历套接字数组 成功握手的 进行数据群发
      foreach ($this->socs as $keys => $values) {
        //用系统分配的套接字资源id作为用户昵称
          $mess['name']="Tourist'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));
        }
    }
Nach dem Login kopieren

7. Betriebsmethode

Github-Adresse git@github.com:rsaLive/websocket.git

①Am besten führen Sie server.php in der Konsole aus

Gehen Sie zum Skriptverzeichnis server.php (Sie können zuerst php -v verwenden, um zu sehen, ob PHP konfiguriert ist. Wenn keine Linux-Konfiguration vorhanden ist, konfigurieren Sie den Pfad in Bash-Fenstern)

php -f server.php

Wenn ein Fehler vorliegt, wird eine Meldung angezeigt

②Zugriff auf HTML-Dateien über den Server

8. Öffnen Sie bei aufgetretenen Fallstricken das Debugging, um Fehler anzuzeigen

①server.php kann die Ausgabe im angehaltenen Prozess drucken. Wenn ein Problem auftritt, können Sie dem Code zum Debuggen das Drucken hinzufügen

Sie können jedes Urteil markieren und in der Konsole überprüfen, in welchem ​​Abschnitt der Code ausgeführt wird

Sie müssen jedoch das Skript php server.php jedes Mal erneut ausführen, nachdem Sie den Code geändert haben

②Wenn dieser Fehler auftritt, liegt es möglicherweise an

1. Senden Sie Daten beim Initialisieren des Sockets mit dem Server (Inhalte können nicht während des ersten Verifizierungs-Handshakes mit dem Server gesendet werden)

2. Dies geschieht auch, wenn es überprüft wurde, der Kunde es aber nicht gesendet hat oder die gesendete Nachricht leer ist

Überprüfen Sie daher die Daten der angeschlossenen Steckdose

③ Möglicherweise unterstützt der Browser dies nicht oder der Server öffnet den Socket nicht. Überprüfen Sie dies am besten, bevor Sie beginnen

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

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich sein wird. Ich hoffe auch, dass jeder Script House unterstützt.

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
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!