socket学习纪录5: workerman 通过API接口调用workerman,后台推送消息至客户端
workerman与其它mvc框架结合建议以下图的方式(ThinkPHP为例):
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中完成。
外层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)