Analyse des messages du client WebSocket
Précédemment, nous avons démontré que lorsque le client se connecte au serveur, un événement de connexion sera déclenché dans le. événement dont nous avons besoin Renvoie le fd du client actuel. Lorsque le client envoie un message au serveur, le serveur enverra le message au client du fd spécifié selon nos règles :
app/listener/WsConnect.php
<?php declare (strict_types = 1); namespace app\listener; class WsConnect { /** * 事件监听处理 * * @return mixed * 受用 WebSocket 客户端连接入口 */ public function handle($event) { //实例化 Websocket 类 $ws = app('\think\swoole\Websocket'); // $ws -> emit('sendfd',$ws -> getSender()); } }
app/ Listener/ WsTest.php
<?php declare (strict_types = 1); namespace app\listener; use \think\swoole\Websocket; class WsTest { /** * 事件监听处理 * * @return mixed */ public function handle($event,Websocket $ws) { $ws -> to(intval($event['to'])) -> emit('testcallback',$event['message']); } }
Après que le client ait exécuté les deux événements ci-dessus, la console affiche les informations suivantes :
Il y a quelques chiffres devant des informations de retour, 40, Que signifie 42 ?
Étant donné que l'extension que nous utilisons est basée sur le protocole SocketIO, ces chiffres peuvent être compris comme le nom de code du protocole.
Ouvrez /vendor/topthink/think-swoole/src/websocket/socketio/Packet.php, il y a le contenu suivant :
Ce qui précède est le type de Socket, Voici le moteur. Les deux noms de code avant et après sont reconstitués :
40:”MESSAGE CONNECT” 42:”MESSAGE EVENT”
En combinant ces codes, vous pouvez connaître le fonctionnement général des messages dans SocketIO.
Nous avons constaté que les messages imprimés via la console ne peuvent pas être utilisés directement et doivent être interceptés et traités :
test.html
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> 消息:<input type="text" id="message"> 接收者:<input type="text" id="to"> <button onclick="send()">发送</button> <script> var ws = new WebSocket("ws://127.0.0.1:9501/"); ws.onopen = function(){ console.log('连接成功'); } //数据返回的解析 function mycallback(data){ var start = data.indexOf('[') // 第一次出现的位置 var start1 = data.indexOf('{') if(start < 0){ start = start1; } if(start >= 0 && start1 >= 0){ start = Math.min(start,start1); } if(start >= 0){ console.log(data); var json = data.substr(start); //截取 var json = JSON.parse(json); console.log(json); } } ws.onmessage = function(data){ // console.log(data.data); mycallback(data.data); } ws.onclose = function(){ console.log('连接断开'); } function send() { var message = document.getElementById('message').value; var to = document.getElementById('to').value; console.log("准备给" + to + "发送数据:" + message); ws.send(JSON.stringify(['test',{ to:to, message:message }])); //发送的数据必须是 ['test',数据] 这种格式 } </script> </body> </html>
Données analysées :
Utilisez SocketIO pour traiter les messages
Pour des connaissances connexes sur SocketIO, vous pouvez consulter la documentation, en vous concentrant sur la connaissance du client :
https:/ /www.w3cschool.cn/socket/socket-k49j2eia.html
iotest.html
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> 消息:<input type="text" id="message"> 接收者:<input type="text" id="to"> <button onclick="send()">发送</button> <script src="./socketio.js"></script> <script> //http 协议 var socket = io("http://127.0.0.1:9501", {transports: ['websocket']}); socket.on('connect', function(){ console.log('connect success'); }); socket.on('close',function(){ console.log('connect close') }); //send_fd 为自定义的场景值,和后端对应 socket.on("sendfd", function (data) { console.log(data) }); //testcallback 为自定义的场景值,和后端对应 socket.on("testcallback", function (data) { console.log(data) }); function send() { var message = document.getElementById('message').value; var to = document.getElementById('to').value; socket.emit('test', { //属性可自行添加 to:to, message:message }) } </script> </body> </html>
var socket = io("http://127.0.0.1:9501", {transports : ['websocket']}); Le deuxième paramètre spécifie le protocole à mettre à niveau.
app/listener/WsConnect.php
<?php declare (strict_types = 1); namespace app\listener; class WsConnect { /** * 事件监听处理 * * @return mixed * 受用 WebSocket 客户端连接入口 */ public function handle($event) { //实例化 Websocket 类 $ws = app('\think\swoole\Websocket'); // $ws -> emit('sendfd',$ws -> getSender()); } }
app/listener/WsTest.php
<?php declare (strict_types = 1); namespace app\listener; use \think\swoole\Websocket; class WsTest { /** * 事件监听处理 * * @return mixed */ public function handle($event,Websocket $ws) { // $ws -> to(intval($event['to'])) -> emit('testcallback',$event['message']); $ws -> to(intval($event['to'])) -> emit('testcallback',[ 'form' => [ 'id' => 10, 'fd' => $ws -> getSender(), 'nickname' => '张三' ], 'to' => [ 'id' => 11, 'fd' => intval($event['to']), 'nickname' => '李四' ], 'massage' => [ 'id' => 888, 'create_time' => '2020-03-13', 'content' => $event['message'] ] ]); } }
Ouvrez deux clients, fd sont respectivement 5 et 6 :
Dans WsConnect.php, il y a $ws -> submit('sendfd',$ws -> getSender()); La valeur de scène correspondant au message send fd est "sendfd". " , dans iotest.html, il y a socket.on("sendfd", function (data) {console.log(data)}); ce code, qui a aussi la valeur de scène "sendfd", cette ligne de code peut directement obtenez les informations de valeur de scène correspondantes, de sorte que la valeur fd sera imprimée sur la console.
Utilisez fd 5 pour envoyer un message à fd 6 :
Les deux clients recevront le message :
On peut voir que le message a été analysé, car le message envoyé dans WsTest.php spécifie la valeur de la scène testcallback, et dans iotest.html, socket.on("testcallback", function (data){console. log(data)}); peut être utilisé pour obtenir directement les résultats analysés.
Cela montre la commodité de SocketIO pour recevoir des messages clients.
Liaison de l'UID de l'utilisateur et du client fd
Dans les exemples précédents, les messages sont envoyés au client en spécifiant fd. Dans les scénarios réels, il nous est impossible de déterminer l'objet d'envoi via fd. , car fd n'est pas fixe, l'UID de l'utilisateur doit donc être lié au fd du client, puis le fd peut être sélectionné pour terminer l'envoi du message.
Il vous suffit d'ajouter le paramètre UID à la connexion HTTP de la page front-end :
test.html
var ws = new WebSocket("ws://127.0.0.1:9501/?uid=1");
iotest.html
var socket = io("http://127.0.0.1:9501?uid=1", {transports: ['websocket']});
Le back-end peut se lier à l'événement de connexion :
app/listener/WsConnect.php
<?php declare (strict_types = 1); namespace app\listener; class WsConnect { /** * 事件监听处理 * * @return mixed * 受用 WebSocket 客户端连接入口 */ public function handle($event) { // $event 为请求对象 //实例化 Websocket 类 $ws = app('\think\swoole\Websocket'); //获取 uid $uid = $event -> get('uid'); //获取 fd $fd = $ws -> getSender(); //获取到 uid 和 fd 后,可以存数据库,内存或者 redis $ws -> emit('sendfd',[ 'uid' => $uid, 'fd' => $fd ]); } }
Avec UID et fd, vous pouvez mettre à jour la base de données après chaque connexion réussie, puis redémarrer une fois la connexion déconnectée, effacez le FD de l'utilisateur. Si le serveur est redémarré, la relation correspondante entre les deux sera inutile, il n'est donc pas nécessaire de la stocker dans la base de données. Il est également préférable de la stocker dans Redis. C'est également un bon choix pour cartographier la relation entre les deux. via le hachage de Redis.
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!