Maison > cadre php > PensezPHP > le corps du texte

WebSocket-Room de Think-Swoole rejoint, quitte la salle et envoie des messages à la salle

Libérer: 2020-10-21 17:17:35
avant
2896 Les gens l'ont consulté

WebSocket-Room de Think-Swoole rejoint, quitte la salle et envoie des messages à la salle

Think-Swoole 3.0 a ajouté la fonction de salle de discussion Room à Websocket, qui est principalement utilisée pour la messagerie de groupe, mais les messages entre différentes salles sont isolés les uns des autres. Lorsque nous entrons dans une salle de discussion, seul le fd de cette salle de discussion peut recevoir les messages que nous entrons, laissons et envoyons.

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'     => [],
    ],
Copier après la connexion

Il y a un élément de configuration de la salle, et le type à l'intérieur indique quelle méthode de traitement des données est utilisée. Il existe deux types ci-dessous, "table" et "redis", table is Il peut être utilisé directement, mais redis nécessite que l'extension redis soit installée dans notre système et notre projet. table est un service de traitement de mémoire inter-processus hautes performances qui peut partager des données entre différents processus.

Créer des événements

Entrez les commandes suivantes dans le répertoire racine du projet pour créer respectivement des événements de participation à la salle, des événements de sortie de salle et des événements de discussion en salle :

php think make:listener WsJoin
php think make:listener WsLeave
php think make:listener RoomTest
Copier après la connexion

Définissez ensuite l'événement dans 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' => [
    ],
];
Copier après la connexion

Les noms ci-dessus tels que Join, Leave et RoomTest sont tous personnalisés et doivent correspondre à la valeur de scène du message envoyé par le front-end.

Bien sûr, la définition de l'événement peut également être configurée dans l'écoute websocket du fichier de configuration config/swoole.php. Veuillez vous référer à l'article précédent pour plus de détails.

Connexion client 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(&#39;连接成功&#39;);
    }
    //数据返回的解析
    function mycallback(data){
        var start = data.indexOf(&#39;[&#39;) // 第一次出现的位置
        var start1 = data.indexOf(&#39;{&#39;)
        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(&#39;连接断开&#39;);
    }
    function join()
{
        var room = prompt(&#39;请输入房间号&#39;);
        ws.send(JSON.stringify([&#39;join&#39;,{
            room:room
        }])); //发送的数据必须是 [&#39;test&#39;,数据] 这种格式
    }
    function leave()
{
        var room = prompt(&#39;请输入要离开的房间号&#39;);
        ws.send(JSON.stringify([&#39;leave&#39;,{
            room:room
        }])); //发送的数据必须是 [&#39;test&#39;,数据] 这种格式
    }
    function send()
{
        var message = document.getElementById(&#39;message&#39;).value;
        var room = prompt(&#39;请输入接收消息的房间号&#39;)
        ws.send(JSON.stringify([&#39;RoomTest&#39;,{
            message:message,
            room:room
        }])); //发送的数据必须是 [&#39;test&#39;,数据] 这种格式
    }
</script>
</body>
</html>
Copier après la connexion

Connexion client 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: [&#39;websocket&#39;]});
    socket.on(&#39;connect&#39;, function(){
        console.log(&#39;connect success&#39;);
    });
    socket.on(&#39;close&#39;,function(){
       console.log(&#39;connect close&#39;)
    });
    //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(&#39;请输入房间号&#39;);
        socket.emit(&#39;join&#39;,{
            room : room
        });
    }
    function leave()
{
        var room = prompt(&#39;请输入要离开的房间号&#39;);
        socket.emit(&#39;leave&#39;,{
            room : room
        });
    }
    function send()
{
        var message = document.getElementById(&#39;message&#39;).value;
        var room = prompt(&#39;请输入接收消息的房间号&#39;)
        socket.emit(&#39;RoomTest&#39;,{
            message : message,
            room : room
        });
    }
</script>
</body>
</html>
Copier après la connexion

, les valeurs de scène définies dans les fonctions join(), Leave() et send() sont respectivement join, Leave et RoomTest, que nous avons définies dans app/leave.php. Ces scènes les valeurs correspondent à des événements et déclenchent donc respectivement les événements WsJoin.php, WsLeave.php et RoomTest.php.

Écriture d'événements backend

app/listener/WsJoin.php

<?php
declare (strict_types = 1);
namespace app\listener;
class WsJoin
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
{
        $ws = app(&#39;think\swoole\Websocket&#39;);
        $roomobj = app(&#39;think\swoole\websocket\Room&#39;);
        //当前客户端加入指定 Room
        $ws -> join($event[&#39;room&#39;]);
        //同时加入多个房间
//        $ws -> join([&#39;room1&#39;,&#39;room2&#39;]);
        //指定客户端加入指定 room
//        $ws -> setSender(2) -> join($event[&#39;room&#39;]);
        //获取当前房间所有的 fd
        $getAllFdInRoom = $roomobj -> getClients($event[&#39;room&#39;]);
        //获取指定 fd 加入哪些房间
        $getAllRoom = $roomobj -> getRooms($ws -> getSender());
        var_dump(&#39;当前房间所有 fd:&#39;,$getAllFdInRoom);
        var_dump(&#39;当前 fd 加入的所有房间:&#39;,$getAllRoom);
        var_dump(&#39;当前请求数据:&#39;,$event);
        $ws -> emit(&#39;joincallback&#39;,&#39;房间加入成功&#39;);
    }
}
Copier après la connexion

app/listener/WsLeave.php

<?php
declare (strict_types = 1);
namespace app\listener;
class WsLeave
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
{
        $ws = app(&#39;think\swoole\Websocket&#39;);
        $roomobj = app(&#39;think\swoole\websocket\Room&#39;);
        // 当前客户端离开指定 room
        $ws -> leave($event[&#39;room&#39;]);
        // 同时离开多个 room
//        $ws -> leave([&#39;one&#39;,&#39;two&#39;]);
        // 指定客户端离开指定 room
//        $ws -> setSender(2) -> leave($event[&#39;room&#39;]);
        // 获取指定 room 中的所有客户端 fd
        $getAllFdInRoom = $roomobj -> getClients($event[&#39;room&#39;]);
        var_dump(&#39;当前房间还剩 fd:&#39;,$getAllFdInRoom);
        $ws -> emit(&#39;leavecallback&#39;,&#39;房间离开成功&#39;);
    }
}
Copier après la connexion

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(&#39;think\swoole\Websocket&#39;);
        //给指定的 room 内所有 fd 发送消息,包括当前客户端,当前客户端没有加入该 room 也可发送
        $ws -> to($event[&#39;room&#39;]) -> emit(&#39;roomtestcallback&#39;,$event[&#39;message&#39;]);
        //指定多个 room 发送消息
        //$ws -> to([&#39;one&#39;,&#39;two&#39;]) -> emit(&#39;客户端场景值&#39;,$event[&#39;message&#39;]);
    }
}
Copier après la connexion

Ce qui précède sont la page HTML frontale et les codes d'événement de participation à la salle, de sortie de la salle et de discussion en salle. Commençons les tests.

Activez d'abord le service Think-Swoole dans le répertoire racine du projet.

Lorsque vous accédez à la page wsroot.html ou ioroomtest.html avec votre navigateur, vous pouvez ouvrir plusieurs onglets et simuler plusieurs clients. Nous en ouvrons trois d'abord. Une fois la connexion réussie, les fds sont 1, 2,. et 3 respectivement. Nous laissons les clients avec fd 1 et 2 rejoindre la salle "un", et le client avec fd 3 rejoindre la salle "deux" puisque nous imprimons tous les fds que l'utilisateur rejoint dans la salle dans WsJoin. .php join room event, et les fds de l'utilisateur. Noms de toutes les salles rejointes, ces informations seront imprimées dans la ligne de commande, et enfin la valeur de la scène de discussion et le message "Rejoindre la salle avec succès" seront envoyés au client actuel. , qui peut être consulté dans la console du navigateur.

Après avoir rejoint la salle, utilisez le client avec fd 1 pour saisir le message à envoyer dans la zone de saisie de la page. Après avoir cliqué sur Envoyer, saisissez le nom de la salle à envoyer comme "une", puis le message sera envoyé à la salle "une", seuls tous les clients de la salle "une" (fd est 1 et 2) peuvent recevoir le message.

Maintenant, laissez le client avec fd 2 quitter la salle "one". Puisque dans l'événement de sortie de salle WsLeave.php, nous imprimons le fd restant après avoir quitté, les informations apparaîtront dans la ligne de commande, visible "one". " Il ne reste plus que le fd 1 dans la pièce. Le fd 1 envoie des informations, mais le fd 2 ne peut pas les recevoir.

D'autres fonctions de WebSocket-Room ont été commentées dans le code ci-dessus et doivent être ouvertes pour tests.

H5 WebSocket et SocketIO ont déjà démontré le traitement des messages dans l'article précédent. Le premier nécessite une analyse manuelle des messages renvoyés par le serveur avant de pouvoir être utilisés, tandis que le second recevra les messages selon le valeur de scène des messages et l'avons fait, le traitement peut être utilisé directement.

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!

Étiquettes associées:
source:阿dai哥
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!