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();
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:
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; }
2. Stecken Sie den Sockel in das Array
public function __construct($address,$port) { //建立套接字 $this->soc=$this->createSocket($address,$port); $this->socs=array($this->soc); }
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); } } } } }
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; }
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; }
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)); } }
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."); }
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.