Avant l'émergence des sockets, il existait déjà des solutions telles que les requêtes planifiées ajax et les interrogations longues, mais aucune d'entre elles ne pouvait répondre aux besoins, c'est pourquoi les sockets sont nées. Cet article 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 et jetons un œil. J'espère que cela pourra aider tout le monde.
Fonction de base du socket socket
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'IP et le port numéro
socket_listen écoute
socket_accept connexion client
socket_read lit les données du client
socket_write envoie des données à un seul client
socket_close Fermez le connection
Client : socket_create Créer un socket et définir les paramètres de base
socket_connect Connecter le socket
socket_write Envoyer des données au serveur
socket_read Lire les données du serveur
socket_close ferme la connexion
H5websocket Pas grand chose à dire, téléchargez le lien
OK, commencez à poster le code~
--------- -------------------------------------------------segmentation 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);
Code client (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 (volé à l'exploitation et à la maintenance ) Apprenez une astuce, 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. Le tableau $handshake enregistre si la connexion est dans l'état de connexion ;
Recommandations associées :
Workerman du framework de serveur de socket PHP
Introduction détaillée à websocket en php
Explication détaillée du module socket en python
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!