Maison > cadre php > Workerman > Comment Workman implémente le système de chat

Comment Workman implémente le système de chat

Libérer: 2019-12-12 14:03:12
original
3515 Les gens l'ont consulté

Comment Workman implémente le système de chat

Installez thinkphp5.1

composer create-project topthink/think=5.1.x-dev tp5andWorkerman
Copier après la connexion

Installez think-worker

composer require topthink/think-worker=2.0.*
Copier après la connexion

Installez Workerman directement

composer require workerman/workerman
Copier après la connexion

(2) Regardons c'est d'abord think-worker code

config/worker_server.php
Copier après la connexion

Prenons d'abord un exemple de serveur diffusant un message Un message est diffusé régulièrement toutes les 10 secondes

'onWorkerStart'  => function ($worker) {
    \Workerman\Lib\Timer::add(10, function()use($worker){
        // 遍历当前进程所有的客户端连接,发送自定义消息
        foreach($worker->connections as $connection){
            $send['name'] = '系统信息';
            $send['content'] = '这是一个定时任务信息';
            $send['time'] = time();
            $connection->send(json_encode($send));
        }
    });}
Copier après la connexion

Mais pendant onMessage, on ne parvient pas à récupérer le $worker. objet, donc impossible de diffuser le message.

'onMessage'      => function ($connection, $data) {
    $origin = json_decode($data,true);
    $send['name'] = '广播数据';
    $send['content'] = $origin['content'];
    $message = json_encode($send);

    foreach($worker->connections as $connection)
    {
        $connection->send($message);
    }}
Copier après la connexion

Modifiez le code à l'intérieur du framework : /vendor/topthink/think-worker/src/command/Server.php, principalement pour ajouter vous-même la méthode onMessage

use() consiste à ajouter l'externe Transmettez la variable à la fonction pour un usage interne, ou utilisez global $worker

$worker = new Worker($socket, $context);$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    $send['name'] = '广播数据';
    $send['content'] = $origin['content'];
    $send['uid'] = $connection->uid;
    $message = json_encode($send);
    foreach($worker->connections as $connection)
    {
        $connection->send($message);
    }};
Copier après la connexion

De cette façon, nous pouvons obtenir l'objet $worker

$worker->onMessage = function ( $connection, $data )use($worker) { ... }

(3) $connection est lié à uid

En fait, vous avez déjà vu que $worker ->les connexions obtenues sont les connexions de tous les utilisateurs actuels, et les connexions sont l'un des liens.

Enregistrer le temps de connexion au websocket :

$worker->onConnect = function ($connection) {
    $connection->login_time = time();};
Copier après la connexion

Obtenir le temps de connexion au websocket :

$worker->onMessage = function ($connection, $data)use($worker) {
    $login_time = $connection->login_time;};
Copier après la connexion

À partir de là, nous pouvons voir que nous pouvons lier des données à un attribut de la connexion $connection, pour exemple :

$connection->uid = $uid;
Copier après la connexion

Lorsque le côté JavaScript se connecte avec succès au serveur websocket, il envoie immédiatement son uid au serveur pour liaison :

var uid = 600;ws.onopen = function() {
    ws.send(JSON.stringify({bind:'yes',uid:uid}));};
Copier après la connexion
$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    if(array_key_exists('bind',$origin)){
        $connection->uid = $origin['uid'];
    }};
Copier après la connexion

(4) Message Unicast, c'est-à-dire envoi personnalisé

$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    $sendTo = $origin['sendto']; // 需要发送的对方的uid
    $content = $origin['content']; // 需要发送到对方的内容
    foreach($worker->connections as $connection)
    {
        if( $connection->uid == $sendTo){
            $connection->send($content);
        }
    }};
Copier après la connexion

À ce stade, l'envoi de messages basés sur l'objet personnalisé de Workerman est terminé.

Puisque le fichier php est stocké dans composer, il vous suffit de copier le fichier, de le mettre dans l'application/commande, de modifier l'espace de noms et de l'enregistrer dans votre propre projet

(5) Stockage des enregistrements de discussion

L'utilisation de Redis pour la mise en cache a moins d'impact sur le serveur et n'affecte fondamentalement pas le temps de réponse

1 Stockez les enregistrements de discussion dans Redis et utilisez le stockage de liste

$message = json_decode($data,true); // $data为接收到的数据
$redis_instance = Cache::handler(); // TP5代码获取Cache实例
$redis_instance->lPush('message',json_encode($message,JSON_UNESCAPED_UNICODE));
Copier après la connexion
<🎜. >2. Dans certains cas, lorsque l'utilisateur (ou actualise) pour la première fois la page de discussion, les 10 derniers enregistrements sont affichés

$redis_instance = Cache::handler(); // TP5代码获取Cache实例
$worker->onConnect = function ($connection)use($redis_instance) {
    $length = $redis_instance->lLen(&#39;message&#39;);
    if($length > 0){
        $send[&#39;recently&#39;] = array_reverse($redis_instance->lRange(&#39;message&#39;, 0, 10));
        $send[&#39;state&#39;] = 200;
        $message = json_encode($send,JSON_UNESCAPED_UNICODE);
        $connection->send($message);
    }else{
        $send[&#39;state&#39;] = 204;
        $send[&#39;recently&#39;] = [];
        $send[&#39;msg&#39;] = &#39;暂无聊天记录&#39;;
        $message = json_encode($send,JSON_UNESCAPED_UNICODE);
        $connection->send($message);
    }
};
Copier après la connexion

Lorsque javascript obtient les enregistrements de discussion récemment récents, ils sont traités :

ws.onmessage = function(e) {
    var your = JSON.parse(e.data);
    if(your.recently){
        // 初次打开页面,渲染最近10条聊天记录
        $.each(your.recently,function(index,item){
            item = JSON.parse(item);
            // TODO:遍历渲染页面
        });
    }else{
        // 处理其他消息
        msglist.append(&#39;<li>&#39;+your.content+&#39;</li>&#39;);
    }
};
Copier après la connexion
Recommandé :

Tutoriel ouvrier

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:php.cn
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