Maison > développement back-end > tutoriel php > Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workerman's GatewayWorker

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workerman's GatewayWorker

藏色散人
Libérer: 2023-04-05 19:32:01
avant
8737 Les gens l'ont consulté

GatewayWorker est un framework de connexion longue TCP déployable distribué développé sur la base de Workerman. Il est spécialement utilisé pour développer rapidement des applications de connexion longue TCP, telles que les serveurs push d'applications, les serveurs de messagerie instantanée, les serveurs de jeux, l'Internet des objets et les maisons intelligentes. Attendez

Adresse du document : http://www.workerman.net/gatewaydoc/

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

1. Testez la DÉMO officielle (version Windows)

1. Téléchargez la démo (Obtenez-la dans les commentaires ci-dessous )

2. Décompressez-la n'importe où, la voici :

D:\phpStudy\PHPTutorial\WWW\GatewayWorker
Copier après la connexion

3. Entrez dans le répertoire GatewayWorker

4. Double-cliquez sur start_for_win.bat pour démarrer. (Si une erreur se produit, veuillez vous référer à la définition de la variable d'environnement php ici), l'effet est le suivant

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

5. Exécutez telnet 127.0.0.1 8282 dans la fenêtre de ligne de commande , entrez n'importe quel caractère pour discuter (pas pour les tests locaux, veuillez remplacer 127.0.0.1 par l'adresse IP réelle).

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

PS : Ce qui précède indique que le test de connexion TCP est réussi

2 Modifier le websocket de test

<🎜. >1. Besoin de modifier start_gateway.php spécifie le protocole websocket, comme ceci

$gateway = new Gateway(websocket://0.0.0.0:7272);
Copier après la connexion
2. Redémarrez start_for_win.bat

3.

Résumé : Il vous suffit de modifier le protocole et le port d'un fichier (start_gateway.php), et aucune autre modification n'est nécessaire.

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

3. Intégration avec le framework ThinkPHP5.1

(1) Le serveur envoie activement des messages au client

Principe : 1. Le projet de framework TP5.1 et le déploiement indépendant de GatewayWorker n'interfèrent pas l'un avec l'autre

2. Toute la logique métier est demandée depuis la page du site Web (websocket connecté) vers TP5. via post/get.1 Terminé dans le contrôleur du framework

3 GatewayWorker n'accepte pas les données du client, c'est-à-dire que GatewayWorker ne traite aucune logique métier et GatewayWorker n'est utilisé que comme un seul. façon canal push

4 Uniquement lorsque le framework TP5.1 doit pousser activement les données vers le navigateur, l'API de la passerelle (GatewayClient) est appelée dans le framework TP5.1 pour terminer le push

<🎜. >

Étapes spécifiques de mise en œuvre

1. La page du site Web établit une connexion websocket avec le GatewayWorker

2. Lorsque le GatewayWorker constate qu'une page initie une connexion, il envoie le client_id de la connexion correspondante à la page du site

Contenu php de l'événement
ws = new WebSocket("ws://127.0.0.1:7272");
Copier après la connexion

contenu index.html

public static function onConnect($client_id)
{
    $resData = [
        &#39;type&#39; => &#39;init&#39;,
        &#39;client_id&#39; => $client_id,
        &#39;msg&#39; => &#39;connect is success&#39; // 初始化房间信息
    ];
    Gateway::sendToClient($client_id, json_encode($resData));
}
Copier après la connexion

3. La page du site Web déclenche une requête ajax après avoir reçu le client_id (index/chat_room/ bind) envoie le client_id au backend TP5.0, méthode de liaison

4. Après le backend reçoit le client_id, utilisez GatewayClient pour appeler Gateway::bindUid($client_id, $uid) pour comparer le client_id avec la liaison uid actuelle (ID utilisateur ou identifiant unique du client). S'il existe une fonction d'envoi de groupe ou de groupe, vous pouvez également utiliser Gateway::joinGroup($client_id, $group_id) pour ajouter le client_id au groupe correspondant



    
    GatewayWorker的websocket连接


GatewayWorker的websocket连接

Copier après la connexion

Valeur renvoyée après une connexion réussie

/*
 * 用户登录后初始化以及绑定client_id
 */
public function bind()
{
    // 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值
    Gateway::$registerAddress = &#39;127.0.0.1:1238&#39;;
    $uid = $this->userId;
    $group_id = $this->groupId;
    $client_id = request()->param(&#39;client_id&#39;);
    // client_id与uid绑定
    Gateway::bindUid($client_id, $uid);
    // 加入某个群组(可调用多次加入多个群组)
    Gateway::joinGroup($client_id, $group_id);
}
Copier après la connexion


PS : La valeur de retour ci-dessus correspond aux données json renvoyées après la connexion réussie du service GatewayWorker

5 Toutes les requêtes initiées par la page sont directement publiées/accédées au. Framework mvc pour un traitement unifié, y compris l'envoi de messagesÉtude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

Envoyer des messages via sendMessage (le serveur envoie activement des messages au client)

6. certain uid ou un certain groupe pendant le traitement commercial, appelez directement l'interface GatewayClient Gateway::sendToUid Gateway::sendToGroup et attendez l'envoi

Accédez à l'opération sendMessage via le navigateur, testez les résultats

// mvc后端发消息 利用GatewayClient发送 Events.php
public function sendMessage()
{
    // stream_socket_client(): unable to connect to tcp://127.0.0.1:1236
    $uid = $this->userId;
    $group = $this->groupId;
    $message = json_encode([
      &#39;type&#39;=>&#39;say&#39;,
      &#39;msg&#39;=>&#39;Hello ThinkPHP5&#39;
    ]);
    // 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值
    Gateway::$registerAddress = &#39;127.0.0.1:1238&#39;;
    // 向任意uid的网站页面发送数据
    Gateway::sendToUid($uid, $message);
    // 向任意群组的网站页面发送数据,如果开启,则会向页面发送两条一样的消息
    //Gateway::sendToGroup($group, $message);
}
Copier après la connexion

PS : les messages TP5.0 ci-dessus sont envoyés via GatewayClientGateway et n'ont aucune relation directe avec le service GatewayWorker

Ce qui précède est le serveur qui envoie activement des messages au clientÉtude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

Notez la distinction :

1 , Le serveur envoie activement des messages au client

2. Le client envoie des messages au client

(2) Le client envoie des messages au client

Pour modifier l'envoi et la réception de messages client à client, modifiez le fichier Events.php de GatewayWorker ci-dessous (les développeurs doivent uniquement prêter attention à ce fichier)

Page du salon de discussion index.html

public static function onConnect($client_id)
{
    $resData = [
        &#39;type&#39; => &#39;init&#39;,
        &#39;client_id&#39; => $client_id,
        &#39;msg&#39; => &#39;connect is success&#39; // 初始化房间信息
    ];
    Gateway::sendToClient($client_id, json_encode($resData));
}
 
/**
 * 当客户端发来消息时触发
 * @param int $client_id 连接id
 * @param mixed $message 具体消息
 */
public static function onMessage($client_id, $message)
{
    // 服务端console输出
    //echo "msg : $message \r\n";
 
    // 解析数据
    $resData = json_decode($message, true);
    $type = $resData['type'];
    $roomId = $resData['roomId'];
    $userId = $resData['userId']; // 未登录,则传递一个随机
    $userName = $resData['userName']; // 未登录,则传递一个随机
    $content = isset($resData['content']) ? $resData['content'] : 'default content';
     
    //将时间全部置为服务器时间
    $serverTime = date('Y-m-d H:i:s', time());
 
    switch ($type) {
        case 'join':  // 用户进入直播间
            //将客户端加入到某一直播间
            Gateway::joinGroup($client_id, $roomId);
            $resData = [
                'type' => 'join',
                'roomId' => $roomId,
                'userName' => $userName,
                'msg' => "enters the Room", // 发送给客户端的消息,而不是聊天发送的内容
                'joinTime' => $serverTime // 加入时间                   
            ];
 
            // 广播给直播间内所有人,谁?什么时候?加入了那个房间?
            Gateway::sendToGroup($roomId, json_encode($resData));
            break;
        case 'say':  // 用户发表评论
            $resData = [
                'type' => 'say',
                'roomId' => $roomId,
                'userName' => $userName,
                'content' => $content,
                'commentTime' => $serverTime // 发表评论时间
            ];
            // 广播给直播间内所有人
            Gateway::sendToGroup($roomId, json_encode($resData));
            break;
        case 'pong':
            break; // 接收心跳
        default:
            //Gateway::sendToAll($client_id,$json_encode($resData));
            break;
    }
}
Copier après la connexion

Redémarrez le serviceRésultats des tests

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>GatewayWorker的websocket连接</title>
</head>
<body>
<h1>GatewayWorker的websocket连接</h1>
<div>
    websocket send content:<input type="text" style="height: 50px; width: 100%;" name="data" id="data">
    <p></p>
    <button id="submit" onclick="sub()">send info</button>
    <p></p>
    <div id="output"></div>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/reconnecting-websocket/1.0.0/reconnecting-websocket.min.js"></script>
<script language="javascript" type="text/javascript">
    var wsUri = "ws://notes.env:7272/";
    var outputContent;
    var roomId = &#39;L06777&#39;;
    var userId = 4840043;
    var userName = &#39;Tinywan&#39; + Math.random();
 
    // 把当新链接的客户端加入到当前直播间,消息类型:{"type":"join","roomId":"1002","userId":"88","userName":"userName"}
    var joinContent = {
        "type": "join",
        "roomId": roomId,
        "userId": userId,
        "userName": userName
    };
 
    // 初始化页面操作
    function init() {
        outputContent = document.getElementById("output");
        initWebSocket();
    }
 
    function initWebSocket() {
        websocket = new ReconnectingWebSocket(wsUri);
        websocket.onopen = function (evt) {
            onOpen(evt)
        };
        websocket.onclose = function (evt) {
            onClose(evt)
        };
        websocket.onmessage = function (evt) {
            onMessage(evt)
        };
        websocket.onerror = function (evt) {
            onError(evt)
        };
    }
 
    function onOpen(evt) {
        console.log("CONNECTED");
    }
 
    // 接收数据
    function onMessage(evt) {
        var data = eval("(" + evt.data + ")");
        var type = data.type || &#39;&#39;;
        switch (type) {
            case &#39;init&#39;:
                // 把当新链接的客户端加入到当前直播间
                console.log(&#39;-------init--------&#39; + data);
                websocket.send(JSON.stringify(joinContent));
                writeToScreen(&#39;<span style="color: blue;">RESPONSE: &#39; + evt.data + &#39;</span>&#39;);
                break;
            case &#39;join&#39;:
                console.log(&#39;-------join--------&#39; + data);
                writeToScreen(
                    &#39;<span style="color: blue;"> &#39; + &#39; 新用户: &#39; + &#39;</span>&#39; +
                    &#39;<span style="color: red;"> &#39; + data.userName + &#39;</span>&#39; +
                    &#39;<span style="color: green;"> &#39; + data.joinTime + &#39;</span>&#39; +
                    &#39;<span style="color: black;"> &#39; + data.msg + &#39;</span>&#39;
                );
                break;
            case &#39;say&#39;:
                console.log(&#39;say======&#39; + data);
                writeToScreen(
                    &#39;<span style="color: blue;"> &#39; + &#39; Chat: &#39; + &#39;</span>&#39; +
                    &#39;<span style="color: red;"> &#39; + data.userName + &#39;</span>&#39; +
                    &#39;<span style="color: #D2691E;"> &#39; + data.commentTime + &#39;</span>&#39; +
                    &#39;<span style="color: black;"> &#39; + data.content + &#39;</span>&#39;
                );
                break;
            default :
                console.log(data);
                break;
        }
    }
 
    function onError(evt) {
        console.log(&#39;<span style="color: red;">ERROR:</span> &#39; + evt.data);
    }
 
    function onClose(evt) {
        console.log("DISCONNECTED");
    }
 
    function writeToScreen(message) {
        var pre = document.createElement("p");
        pre.style.wordWrap = "break-word";
        pre.innerHTML = message;
        outputContent.appendChild(pre);
    }
 
    function sub() {
        var text = document.getElementById(&#39;data&#39;).value;
        // {"type":"say",,"msg":"Welcome 111111111111Live Room"}
        var sayContent = {
            "type": "say",
            "roomId": roomId,
            "userId": userId,
            "userName": userName,
            "content": text
        };
        websocket.send(JSON.stringify(sayContent));
    }
    window.addEventListener("load", init, false);
</script>
</body>
</html> 
Copier après la connexion

Extension :

Étude de cas de la combinaison du framework ThinkPHP5.1 et du framework Workermans GatewayWorker

Oui Stockez les messages dans Redis et comptez le PV de la salle de diffusion en direct via Redis

$redis = new \Redis;
$redis->connect(&#39;127.0.0.1&#39;,6379);
$key = "PV:ROOM:".$roomId;
$field = "ROOM_TOTAL_PV";
// 进入房间的人数增长,自增 ,增加PV统计
$redis->hIncrBy($key,$field,1);
Copier après la connexion

相关推荐:《PHP教程

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:cnblogs.com
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