Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workerman's GatewayWorker-Frameworks

藏色散人
Freigeben: 2023-04-05 19:32:01
nach vorne
8570 Leute haben es durchsucht

GatewayWorker ist ein verteilt einsetzbares TCP-Framework für lange Verbindungen, das auf Workerman basiert. Es wird speziell für die schnelle Entwicklung von TCP-Anwendungen für lange Verbindungen verwendet, z. B. App-Push-Server, Instant-IM-Server, Spieleserver, Internet der Dinge und Smart Homes. Warten

Dokumentadresse: http://www.workerman.net/gatewaydoc/

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-Frameworks

1. Testen Sie die offizielle DEMO (Windows-Version).

1. Laden Sie die Demo herunter (Laden Sie sie in den Kommentaren herunter )

2. Entpacken Sie sie an einen beliebigen Ort, meiner ist:

D:\phpStudy\PHPTutorial\WWW\GatewayWorker
Nach dem Login kopieren

3. Geben Sie das GatewayWorker-Verzeichnis ein

4. Doppelklicken Sie auf start_for_win.bat, um zu starten. (Wenn ein Fehler auftritt, lesen Sie bitte hier die Einstellung der PHP-Umgebungsvariablen). Die Auswirkung ist wie folgt:

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-Frameworks

5. Führen Sie Telnet 127.0.0.1 8282 im Befehlszeilenfenster aus Geben Sie zum Chatten beliebige Zeichen ein (nicht). Für lokale Tests ersetzen Sie bitte 127.0.0.1 durch die tatsächliche IP.

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-Frameworks

PS: Das Obige zeigt an, dass der TCP-Verbindungstest erfolgreich war

2. Ändern Sie den Test-Websocket

1. Start_gateway.php muss wie folgt geändert werden

$gateway = new Gateway(websocket://0.0.0.0:7272);
Nach dem Login kopieren

2. Starten Sie start_for_win.bat

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-Frameworks Zusammenfassung: Sie müssen nur das Protokoll und den Port einer Datei (start_gateway.php) ändern, sonst muss nichts geändert werden.

3. Integration mit dem ThinkPHP5.1-Framework

(1) Der Server sendet aktiv Nachrichten an den Client

Prinzip :

1. Das TP5.1-Framework-Projekt und die unabhängige Bereitstellung von GatewayWorker beeinträchtigen sich nicht gegenseitig

2. Die gesamte Geschäftslogik wird von der Website-Seite (Websocket-verbunden) an TP5 angefordert durch post/get. 1 Wird im Controller des Frameworks abgeschlossen

3 GatewayWorker akzeptiert keine Daten vom Client, d. Weg-Push-Kanal

4. Nur wenn das TP5.1-Framework Daten aktiv an den Browser pushen muss, wird die Gateway-API (GatewayClient) im TP5.1-Framework aufgerufen, um den Push abzuschließen

Spezifische Implementierungsschritte

1. Die Website-Seite stellt eine Websocket-Verbindung mit GatewayWorker her

ws = new WebSocket("ws://127.0.0.1:7272");
Nach dem Login kopieren

2. Wenn GatewayWorker feststellt, dass eine Seite eine Verbindung initiiert, sendet es die client_id der entsprechenden Verbindung zur Website-Seite

Event.php-Inhalt

public static function onConnect($client_id)
{
    $resData = [
        'type' => 'init',
        'client_id' => $client_id,
        'msg' => 'connect is success' // 初始化房间信息
    ];
    Gateway::sendToClient($client_id, json_encode($resData));
}
Nach dem Login kopieren

index.html-Inhalt




    
    GatewayWorker的websocket连接


GatewayWorker的websocket连接

Nach dem Login kopieren
3. Nachdem die Website-Seite die client_id erhalten hat, löst sie eine Ajax-Anfrage (index/chat_room/bind) aus, um die client_id an das TP5.0-Backend zu senden, Bind-Methode

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

4. Nach dem Empfang der client_id verwendet das Backend GatewayClient um Gateway::bindUid($client_id, $uid) aufzurufen, um die client_id mit der aktuellen uid-Bindung (Benutzer-ID oder eindeutige Client-ID) zu vergleichen. Wenn es eine Gruppen- oder Gruppensendefunktion gibt, können Sie auch Gateway::joinGroup($client_id, $group_id) verwenden, um die client_id zur entsprechenden Gruppe hinzuzufügen

Rückgabewert nach erfolgreicher Verbindung


Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-FrameworksPS: Der obige Rückgabewert sind die JSON-Daten, die zurückgegeben werden, nachdem der GatewayWorker-Dienst erfolgreich verbunden wurde

5 Alle von der Seite initiierten Anfragen werden direkt gesendet/abgerufen das MVC-Framework für die einheitliche Verarbeitung, einschließlich des Sendens von Nachrichten

Nachrichten über sendMessage senden (der Server sendet Nachrichten aktiv an den Client)

// 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([
      'type'=>'say',
      'msg'=>'Hello ThinkPHP5'
    ]);
    // 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值
    Gateway::$registerAddress = '127.0.0.1:1238';
    // 向任意uid的网站页面发送数据
    Gateway::sendToUid($uid, $message);
    // 向任意群组的网站页面发送数据,如果开启,则会向页面发送两条一样的消息
    //Gateway::sendToGroup($group, $message);
}
Nach dem Login kopieren

6. Wenn das MVC-Framework Daten an einen bestimmten senden muss Rufen Sie während der Geschäftsverarbeitung eine uid oder eine Gruppe auf und rufen Sie direkt die GatewayClient-Schnittstelle Gateway::sendToUid Gateway::sendToGroup auf.

Zugriff auf den sendMessage-Vorgang über den Browser und auf die Testergebnisse

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-FrameworksPS: Die obige Nachricht ist TP5.0, das Schreibnachrichten über GatewayClientGateway sendet und keine direkte Beziehung zum GatewayWorker-Dienst hat

Das Obige ist der Server, der aktiv Nachrichten an den Client sendet

Beachten Sie die Unterscheidung:

1. Service Der Client sendet aktiv Nachrichten an den Client

2. Der Client sendet Nachrichten an den Client

(2) Der Client sendet Nachrichten an den Client

Um das Senden und Empfangen von Nachrichten von Client zu Client zu ändern, ändern Sie unten die Events.php von GatewayWorker (Entwickler müssen nur auf diese Datei achten). )

public static function onConnect($client_id)
{
    $resData = [
        'type' => 'init',
        'client_id' => $client_id,
        'msg' => 'connect is success' // 初始化房间信息
    ];
    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;
    }
}
Nach dem Login kopieren

index.html Chatroom-Seite

<!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> 
Nach dem Login kopieren
Dienst neu starten

Testergebnisse

Fallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workermans GatewayWorker-Frameworks

Erweiterung:

Kann Nachrichten in Redis speichern und die PV des Live-Übertragungsraums über Redis zählen

$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);
Nach dem Login kopieren

相关推荐:《PHP教程

Das obige ist der detaillierte Inhalt vonFallstudie der Kombination des ThinkPHP5.1-Frameworks und des Workerman's GatewayWorker-Frameworks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:cnblogs.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!