socket学习纪录5: workerman 通过API接口调用workerman,后台推送消息至客户端

蛰伏已久 蛰伏已久 2018-05-29

workerman与其它mvc框架结合建议以下图的方式(ThinkPHP为例):

workerman-work-with-thinkphp.png

1、ThinkPHP与Workerman是两个独立的系统,独立部署(可部署在不同服务器),互不干扰。

2、ThinkPHP以HTTP协议提供网页页面在浏览器渲染展示。

3、ThinkPHP提供的页面的js发起websocket连接,连接workerman

4、连接后给Workerman发送一个数据包(包含用户名密码或者某种token串)用于验证websocket连接属于哪个用户。

5、仅在ThinkPHP需要向浏览器推送数据时,才调用workerman的socket接口推送数据。

6、其余请求还是按照原本ThinkPHP的HTTP方式调用处理。

把Workerman作为一个可以向浏览器推送的通道,仅仅在需要向浏览器推送数据时才调用Workerman接口完成推送。业务逻辑全部在ThinkPHP中完成。


websocket服务端代码

外层worker为websocket服务,可以接收客户端(如小程序)数据,可以向客户端推送数据;

内层wordker为Text协议,可以接收后台(如thinkphp或YII)的数据,然后根据后台发送的指令,向不同客户端发送消息

<?php


//启动socket服务
require_once __DIR__ . '/Autoloader.php';

use Workerman\Worker;


$ws_worker = new Worker("websocket://0.0.0.0:2347");


// 只启动1个进程,这样方便客户端之间传输数据
$ws_worker->count = 1;

$ws_worker->connection_uids=array();

$ws_worker->onWorkerStart=function($worker){

    $inner_text_work=new Worker("Text://0.0.0.0:5678");
    $inner_text_work->onMessage=function($connection, $buffer){
        $d=json_decode($buffer);

        switch($d->type){
            case 'send_message':
                if($d->to=='all'){
                    echo "向全部用户发送消息\n";
                    broadcast($d->message);
                }else{
                    echo "向用户{$d->to}发送消息\n";
                    sendMessageByUid($d->to,$d->message);
                }
                break;
            default:
                break;

        }
    };

    $inner_text_work->listen();
};
$ws_worker->onMessage = function($connection, $data){
    global $ws_worker;

    $d=json_decode($data);

    switch($d->type){
        case 'login':
            $connection->uid=$d->uid;
            $ws_worker->connection_uids[$d->uid]=$connection;
            echo "收到登录请求,uid={$d->uid}\n";
            break;
        default:
            break;

    }


};
$ws_worker->onClose = function($connection){
    global $ws_worker;

};

function broadcast($message){
    global $ws_worker;
    foreach($ws_worker->connections as $conn){
        $conn->send($message);
    }
}
function sendMessageByUid($uid,$message){
    global $ws_worker;
    if(isset($ws_worker->connection_uids[$uid])){
        $conn=$ws_worker->connection_uids[$uid];
        $conn->send($message);
    }
}


Worker::runAll();


小程序端核心代码

wx.onSocketOpen(function (res) {
console.log('WebSocket连接已打开!')
var data1 = {
type: 'login',
uid: '456'
}
wx.sendSocketMessage({
data: JSON.stringify(data1),
})
})

后台thinkphp或YII核心代码

 public function actionSocket($id){
        $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// 推送的数据,包含uid字段,表示是给这个uid推送
        $data = array('type'=>'send_message','to'=>$id, 'message'=>"$id,你好");
// 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($data)."\n");
// 读取推送结果
        echo fread($client, 8192);
    }



分享到

点赞(2)