Think-Swoole之WebSocket-Room加入、离开房间和房间消息发送
Think-Swoole 3.0 中 Websocket 新增了 Room 聊天室功能,它主要用于群发消息,但不同Room之间的消息又是相互隔离的。当我们进入一个聊天室,那么我们的进入、离开以及发送的消息只有这个聊天室的 fd 能接收到。
config.swoole.php
'websocket' => [ 'enable' => true, 'handler' => Handler::class, 'parser' => Parser::class, 'ping_interval' => 25000, 'ping_timeout' => 60000, 'room' => [ 'type' => 'table', 'table' => [ 'room_rows' => 4096, 'room_size' => 2048, 'client_rows' => 8192, 'client_size' => 2048, ], 'redis' => [ 'host' => '127.0.0.1', 'port' => 6379, 'max_active' => 3, 'max_wait_time' => 5, ], ], 'listen' => [], 'subscribe' => [], ],
其中有 room 配置项,里面的 type 表示使用哪种数据处理方式,下面有两种,“table” 和“redis”,table 是可以直接拿来使用的,而 redis 则需要我们的系统和项目中安装了 redis 扩展。table 是一种高性能、跨进程的内存处理服务,不同进程间可以共享数据。
创建事件
在项目根目录输入如下命令,分别创建加入房间事件、离开房间事件和房间的聊天事件:
php think make:listener WsJoin php think make:listener WsLeave php think make:listener RoomTest
然后在 app/event.php 中定义事件:
[ ], 'listen' => [ 'AppInit' => [], 'HttpRun' => [], 'HttpEnd' => [], 'LogLevel' => [], 'LogWrite' => [], //监听连接,swoole 事件必须以 swoole 开头 'swoole.websocket.Connect' => [ app\listener\WsConnect::class ], //监听关闭 'swoole.websocket.Close' => [ \app\listener\WsClose::class ], //监听 Test 场景 'swoole.websocket.Test' => [ \app\listener\WsTest::class ], //加入房间事件 'swoole.websocket.Join' => [ \app\listener\WsJoin::class ], //离开房间事件 'swoole.websocket.Leave' => [ \app\listener\WsLeave::class ], //处理聊天室消息 'swoole.websocket.RoomTest' => [ \app\listener\RoomTest::class ], ], 'subscribe' => [ ], ];
上述的 Join、Leave和RoomTest等名称都是自定义的,要和前端发送消息的场景值对应。
当然,事件定义一样可以在 config/swoole.php 配置文件的 websocket listen 进行配置,具体参考前面文章。
H5 WebSocker 客户端方式连接
wsroot.html
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <button onclick="join()">加入房间</button> <button onclick="leave()">离开房间</button> <input type="text" id="message"> <button onclick="send()">发送</button> <script> var ws = new WebSocket("ws://127.0.0.1:9501/?uid=1"); 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); // if(json instanceof Array){ // window[json[0]](json[1]); // } } } function sendfd($message){ console.log($message) } function testcallback($message){ console.log($message) } function joincallback($message){ // console.log($message) console.log(11); } function leavecallback($message){ console.log($message) } ws.onmessage = function(data){ // console.log(data.data); mycallback(data.data); } ws.onclose = function(){ console.log('连接断开'); } function join() { var room = prompt('请输入房间号'); ws.send(JSON.stringify(['join',{ room:room }])); //发送的数据必须是 ['test',数据] 这种格式 } function leave() { var room = prompt('请输入要离开的房间号'); ws.send(JSON.stringify(['leave',{ room:room }])); //发送的数据必须是 ['test',数据] 这种格式 } function send() { var message = document.getElementById('message').value; var room = prompt('请输入接收消息的房间号') ws.send(JSON.stringify(['RoomTest',{ message:message, room:room }])); //发送的数据必须是 ['test',数据] 这种格式 } </script> </body> </html>
SocketIO 客户端方式连接
ioroomtest.html
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <button onclick="join()">加入房间</button> <button onclick="leave()">离开房间</button> <input type="text" id="message"> <button onclick="send()">发送</button> <script src="./socketio.js"></script> <script> //http 协议 var socket = io("http://127.0.0.1:9501?uid=1", {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) }); socket.on("joincallback", function (data) { console.log(data) }); socket.on("roomtestcallback", function (data) { console.log(data) }); function join() { var room = prompt('请输入房间号'); socket.emit('join',{ room : room }); } function leave() { var room = prompt('请输入要离开的房间号'); socket.emit('leave',{ room : room }); } function send() { var message = document.getElementById('message').value; var room = prompt('请输入接收消息的房间号') socket.emit('RoomTest',{ message : message, room : room }); } </script> </body> </html>
页面中,join()、leave()、和send() 函数中定义的场景值分别是 join、leave和RoomTest,我们在 app/leave.php 中定义了这些场景值对应的事件,因此分别触发 WsJoin.php、WsLeave.php 和 RoomTest.php 事件。
后端事件编写
app/listener/WsJoin.php
<?php declare (strict_types = 1); namespace app\listener; class WsJoin { /** * 事件监听处理 * * @return mixed */ public function handle($event) { $ws = app('think\swoole\Websocket'); $roomobj = app('think\swoole\websocket\Room'); //当前客户端加入指定 Room $ws -> join($event['room']); //同时加入多个房间 // $ws -> join(['room1','room2']); //指定客户端加入指定 room // $ws -> setSender(2) -> join($event['room']); //获取当前房间所有的 fd $getAllFdInRoom = $roomobj -> getClients($event['room']); //获取指定 fd 加入哪些房间 $getAllRoom = $roomobj -> getRooms($ws -> getSender()); var_dump('当前房间所有 fd:',$getAllFdInRoom); var_dump('当前 fd 加入的所有房间:',$getAllRoom); var_dump('当前请求数据:',$event); $ws -> emit('joincallback','房间加入成功'); } }
app/listener/WsLeave.php
<?php declare (strict_types = 1); namespace app\listener; class WsLeave { /** * 事件监听处理 * * @return mixed */ public function handle($event) { $ws = app('think\swoole\Websocket'); $roomobj = app('think\swoole\websocket\Room'); // 当前客户端离开指定 room $ws -> leave($event['room']); // 同时离开多个 room // $ws -> leave(['one','two']); // 指定客户端离开指定 room // $ws -> setSender(2) -> leave($event['room']); // 获取指定 room 中的所有客户端 fd $getAllFdInRoom = $roomobj -> getClients($event['room']); var_dump('当前房间还剩 fd:',$getAllFdInRoom); $ws -> emit('leavecallback','房间离开成功'); } }
app/listener/RoomTest.php
<?php declare (strict_types = 1); namespace app\listener; class RoomTest { /** * 事件监听处理 * * @return mixed */ public function handle($event) { var_dump($event); $ws = app('think\swoole\Websocket'); //给指定的 room 内所有 fd 发送消息,包括当前客户端,当前客户端没有加入该 room 也可发送 $ws -> to($event['room']) -> emit('roomtestcallback',$event['message']); //指定多个 room 发送消息 //$ws -> to(['one','two']) -> emit('客户端场景值',$event['message']); } }
以上分别是前端 HTML 页面和后端的加入房间、离开房间和房间聊天事件代码,下面开始测试。
首先在项目根目录开启 Think-Swoole 服务。
浏览器访问 wsroot.html 或者 ioroomtest.html 页面,可以打开多个标签,模拟多个客户端,我们先打开三个,连接成功后,fd 分别为1、2、3,我们让 fd 1 和 2 的客户端都加入“one”,房间,fd 为 3 的客户端加入 “two” 房间,由于我们在 WsJoin.php 加入房间事件中打印了用户加入房间所有 fd,和该用户所加入的所有房间名称,这些信息会打印在命令行中,最后会发送给当前客户端聊天场景值和“加入房间成功”信息给客户端,在浏览器控制台可查看。
加入房间后,用 fd 为 1 的客户端在页面的输入框输入要发送的消息,点击发送后,输入要发送的房间名称为“one”,然后,消息就发送到“one”房间,只有“one”房间的所有客户端(fd 为1、2)能收到消息。
现在让 fd 为 2 的客户端离开 “one” 房间,由于在 WsLeave.php 离开房间事件中,我们打印了离开后剩余 fd,信息会出现在命令行中,可见“one”房间只剩下 fd 1 了,fd 1 发送信息,fd 2 就收不到了。
关于 WebSocket-Room 的其他功能,都已经在上述代码中注释了,需要可打开进行测试。
H5 WebSocket 和 SocketIO 对于消息的处理,上篇文章已经演示过了,前者对于服务端返回的消息需要手动解析才能使用,后者会根据消息的场景值接收消息,并做过处理可以直接使用。
Atas ialah kandungan terperinci Think-Swoole之WebSocket-Room加入、离开房间和房间消息发送. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Pengoptimuman prestasi dan penyahpepijatan perkhidmatan TP6Think-SwooleRPC 1. Pengenalan Dengan perkembangan pesat Internet, pengkomputeran teragih telah menjadi bahagian yang amat diperlukan dalam pembangunan perisian moden. Dalam pengkomputeran teragih, RPC (RemoteProcedureCall, Remote Procedure Call) ialah mekanisme komunikasi yang biasa digunakan di mana panggilan kaedah merentas rangkaian boleh dilaksanakan. Think-Swoole, sebagai rangka kerja PHP berprestasi tinggi, boleh menyokong perkhidmatan RPC dengan baik. tetapi

TP6 (ThinkPHP6) ialah rangka kerja sumber terbuka berdasarkan PHP, yang mempunyai ciri-ciri berskala tinggi dan penggunaan teragih. Artikel ini akan memperkenalkan cara menggunakan TP6 dengan sambungan Swoole untuk membina perkhidmatan RPC berskala tinggi dan memberikan contoh kod khusus. Pertama, kita perlu memasang sambungan TP6 dan Swoole. Jalankan arahan berikut dalam baris arahan: composerrequiretopthink/thinkpeclinstallswo

Penyulitan data dan mekanisme pengesahan identiti perkhidmatan TP6Think-SwooleRPC Dengan perkembangan pesat Internet, semakin banyak aplikasi perlu membuat panggilan jauh untuk merealisasikan interaksi data dan panggilan fungsi antara modul yang berbeza. Dalam konteks ini, RPC (RemoteProcedureCall) telah menjadi kaedah komunikasi yang penting. Rangka kerja TP6Think-Swoole boleh melaksanakan perkhidmatan RPC berprestasi tinggi Artikel ini akan memperkenalkan cara menggunakan penyulitan data dan pengesahan identiti.

Pemprosesan permintaan serentak dan penjadualan perkhidmatan TP6Think-SwooleRPC Dengan perkembangan berterusan teknologi Internet, pemprosesan permintaan serentak dan penjadualan aplikasi rangkaian telah menjadi cabaran penting. Dalam rangka kerja TP6, sambungan Think-Swoole boleh digunakan untuk melaksanakan pemprosesan permintaan serentak tinggi dan penjadualan perkhidmatan RPC (RemoteProcedureCall). Artikel ini akan memperkenalkan cara membina perkhidmatan RPC berasaskan Think-Swoole dalam rangka kerja TP6 dan menyediakan

Penyepaduan dan aplikasi perkhidmatan RPC dan baris gilir mesej TP6Think-Swoole Dalam pembangunan perisian moden, perkhidmatan RPC (RemoteProcedureCall) dan baris gilir mesej adalah cara teknikal yang biasa digunakan untuk melaksanakan panggilan perkhidmatan dan pemprosesan mesej tak segerak dalam sistem yang diedarkan. Mengintegrasikan komponen Think-Swoole dalam rangka kerja TP6 boleh melaksanakan fungsi perkhidmatan RPC dan baris gilir mesej dengan mudah, serta menyediakan contoh kod ringkas untuk difahami dan digunakan oleh pembangun. 1. RPC

Perlindungan keselamatan dan pengesahan kebenaran perkhidmatan TP6Think-SwooleRPC Dengan peningkatan pengkomputeran awan dan perkhidmatan mikro, panggilan prosedur jauh (RPC) telah menjadi bahagian yang amat diperlukan dalam kerja harian pembangun. Apabila membangunkan perkhidmatan RPC, perlindungan keselamatan dan pengesahan kebenaran adalah sangat penting untuk memastikan bahawa hanya permintaan yang sah boleh mengakses dan memanggil perkhidmatan tersebut. Artikel ini akan memperkenalkan cara melaksanakan perlindungan keselamatan dan pengesahan kebenaran perkhidmatan RPC dalam rangka kerja TP6Think-Swoole. 1. Konsep asas perkhidmatan RPC

Ujian prestasi dan penalaan prestasi perkhidmatan TP6Think-SwooleRPC 1. Pengenalan Dengan perkembangan pesat Internet, aplikasi sistem teragih menjadi semakin meluas. Dalam sistem teragih, RPC (Remote Procedure Call) ialah mekanisme komunikasi biasa, yang membolehkan perkhidmatan pada nod berbeza untuk memanggil satu sama lain dan mencapai kerja kerjasama dalam sistem teragih. Dalam rangka kerja TP6, Think-Swoole, sebagai pemandu Swoole berprestasi tinggi, menyediakan sokongan perkhidmatan RPC yang mudah. Artikel ini terutamanya memperkenalkan T

Pengenalan kepada kes praktikal perkhidmatan RPC dan seni bina perkhidmatan mikro yang dibina oleh TP6Think-Swoole: Dengan perkembangan pesat Internet dan pengembangan skala perniagaan, seni bina monolitik tradisional tidak lagi dapat memenuhi keperluan senario perniagaan berskala besar. Oleh itu, seni bina perkhidmatan mikro telah wujud. Dalam seni bina perkhidmatan mikro, perkhidmatan RPC (RemoteProcedureCall) adalah cara penting untuk mencapai komunikasi antara perkhidmatan. Melalui perkhidmatan RPC, pelbagai perkhidmatan mikro boleh menghubungi satu sama lain dengan mudah dan cekap. Dalam artikel ini
