Maison >développement back-end >tutoriel php >Exemple d'explication sur la façon d'implémenter la technologie socket push en PHP
L'éditeur ci-dessous partagera avec vous un exemple d'implémentation de la technologie socket push par PHP. Il a une bonne valeur de référence et j'espère qu'il sera utile à tout le monde. Suivons l'éditeur pour y jeter un œil
Avant l'émergence des sockets, il existait déjà des solutions telles que les requêtes planifiées ajax et les longues interrogations, mais elles ne pouvaient pas répondre aux besoins, alors les sockets sont nées.
Fonctions de base du socket socket
Un résumé des fonctions de socket couramment utilisées
Côté serveur : socket_create crée un socket et définit les paramètres de base
socket_bind lie l'adresse IP et le numéro de port
socket_listen écoute
socket_accepte la connexion client
socket_read lit les données du client
socket_write envoie des données à un seul client
socket_close ferme la connexion
Client : socket_create crée un socket et définit les paramètres de base
socket_connect se connecte au socket
socket_write envoie des données au serveur
socket_read lit les données du serveur
socket_close ferme Non beaucoup à dire sur la connexion
H5websocket, il suffit d'aller sur le lien
OK et de commencer à poster le code~
------- -- -----------------------------------------------Séparation ligne
Code serveur :
<?php class WS { var $master; var $sockets = array(); var $debug = false;//true为调试模式,输出log日志 var $handshake = array(); function __construct($address, $port){ $this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed"); socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed"); socket_bind($this->master, $address, $port) or die("socket_bind() failed"); socket_listen($this->master,20) or die("socket_listen() failed"); $this->sockets[] = $this->master; $this->say("Server Started : ".date('Y-m-d H:i:s')); $this->say("Listening on : ".$address." port ".$port); $this->say("Master socket : ".$this->master."\n"); while(true){ $socketArr = $this->sockets; $write = NULL; $except = NULL; socket_select($socketArr, $write, $except, NULL); //自动选择来消息的socket 如果是握手 自动选择主机 foreach ($socketArr as $socket){ if ($socket == $this->master){ //主机 $client = socket_accept($this->master); if ($client < 0){ $this->log("socket_accept() failed"); continue; } else{ $this->connect($client); } } else { $bytes = @socket_recv($socket,$buffer,2048,0); if ($bytes == 0){ $this->disConnect($socket); } else{ $key = array_search($socket, $this->sockets); if (empty($this->handshake) || !isset($this->handshake[$key]) || !$this->handshake[$key]){ $this->doHandShake($socket, $buffer, $key); } else{ $buffer = $this->decode($buffer); echo $buffer.PHP_EOL; $key = array_search($socket, $this->sockets); $arr = $this->sockets; array_shift($arr); foreach ($arr as $s){ $this->send($s, $buffer); } } } } } } } function send($client, $msg){ $msg = $this->frame($msg); socket_write($client, $msg, strlen($msg)); } function connect($socket){ array_push($this->sockets, $socket); $this->say("\n" . $socket . " CONNECTED!"); $this->say(date("Y-n-d H:i:s")); } function disConnect($socket){ $index = array_search($socket, $this->sockets); socket_close($socket); $this->say($socket . " DISCONNECTED!"); if ($index >= 0){ echo 'unset index is:'.PHP_EOL; unset($this->sockets[$index]); } } function doHandShake($socket, $buffer, $handKey){ $this->log("\nRequesting handshake..."); $this->log($buffer); list($resource, $host, $origin, $key) = $this->getHeaders($buffer); $this->log("Handshaking..."); $upgrade = "HTTP/1.1 101 Switching Protocol\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Accept: " . $this->calcKey($key) . "\r\n\r\n"; //必须以两个回车结尾 $this->log($upgrade); $sent = socket_write($socket, $upgrade, strlen($upgrade)); $this->handshake[$handKey]=true; $this->log("Done handshaking..."); return true; } function getHeaders($req){ $r = $h = $o = $key = null; if (preg_match("/GET (.*) HTTP/" ,$req,$match)) { $r = $match[1]; } if (preg_match("/Host: (.*)\r\n/" ,$req,$match)) { $h = $match[1]; } if (preg_match("/Origin: (.*)\r\n/" ,$req,$match)) { $o = $match[1]; } if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)) { $key = $match[1]; } return array($r, $h, $o, $key); } function calcKey($key){ //基于websocket version 13 $accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)); return $accept; } 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; } function frame($s){ $a = str_split($s, 125); if (count($a) == 1){ return "\x81" . chr(strlen($a[0])) . $a[0]; } $ns = ""; foreach ($a as $o){ $ns .= "\x81" . chr(strlen($o)) . $o; } return $ns; } function say($msg = ""){ echo $msg . "\n"; } function log($msg = ""){ if ($this->debug){ echo $msg . "\n"; } } } new WS('localhost', 4000);
Client Code (H5) :
<html> <head> <title>demo</title> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> </head> <body> <input type="text" id="content"> <input type="button" value="send" id="send"> <script type="text/javascript"> var ws = new WebSocket("ws://localhost:4000"); ws.onopen = function(){ console.log("握手成功"); } ws.onmessage = function(e){ console.log("message:" + e.data); } ws.onerror = function(){ console.log("error"); } $("#send").click(function(){ content = $("#content").val(); console.log(content); ws.send(content); }) </script> </body> </html>
Exécutez ensuite php demo.php pour ouvrir le socket (volez une astuce à l'opération et maintenance, exécutez nohup php demo.php & peut être exécuté en arrière-plan sous Linux), le navigateur ouvrira plusieurs index.html et la communication pourra être établie.
Analyse du code :
1. Le tableau d'attribut $sockets enregistre chaque connexion acceptée (je ne sais pas si c'est la bonne description. );
2. L'attribut $handshake array enregistre si la connexion est dans l'état connecté
L'exemple ci-dessus de php implémentant la technologie socket push est tout le contenu partagé par l'éditeur I. j'espère que cela pourra vous donner une référence. J'espère également que tout le monde soutiendra le site Web chinois php.
Explication de comment obtenir l'adresse de livraison partagée WeChat avec PHP
Explication détaillée des étapes pour déployer le projet thinkphp5 sur l'hôte virtuel cloud
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!