|
@@ -0,0 +1,138 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace app\push\controller;
|
|
|
+
|
|
|
+use think\Db;
|
|
|
+use think\worker\Server;
|
|
|
+use Workerman\Lib\Timer;
|
|
|
+
|
|
|
+class Worker extends Server
|
|
|
+{
|
|
|
+ protected $socket = 'websocket://0.0.0.0:2346';
|
|
|
+ protected $snConnections = [];
|
|
|
+ protected $heartbeat_time = '55';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收到信息
|
|
|
+ * @param $connection
|
|
|
+ * @param $data
|
|
|
+ */
|
|
|
+ public function onMessage($connection, $datas)
|
|
|
+ {
|
|
|
+ $connection->lastMessageTime = time();
|
|
|
+ $data = json_decode($datas);
|
|
|
+ if (empty($data->uid)) {
|
|
|
+ $connection->close();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $uid = 1;//这里的uid根据自己的情况去验证
|
|
|
+ if (empty($uid)) {
|
|
|
+ $connection->close();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch ($data->type) {
|
|
|
+ case 'login':
|
|
|
+ // 保存该用户的输送数据
|
|
|
+ $this->uidConnections[$uid] = $connection;
|
|
|
+ // $connection->send('发送成功');
|
|
|
+ break;
|
|
|
+ case 'send':
|
|
|
+ // 发送消息
|
|
|
+ // $this->sendMessageByUid($uid, $datas);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当连接建立时触发的回调函数
|
|
|
+ * @param $connection
|
|
|
+ */
|
|
|
+ public function onConnect($connection)
|
|
|
+ {
|
|
|
+ $connection->send('链接成功');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当连接断开时触发的回调函数
|
|
|
+ * @param $connection
|
|
|
+ */
|
|
|
+ public function onClose($connection)
|
|
|
+ {
|
|
|
+ if(isset($connection->uid))
|
|
|
+ {
|
|
|
+ // 连接断开时删除映射
|
|
|
+ unset($this->uidConnections[$connection->uid]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当客户端的连接上发生错误时触发
|
|
|
+ * @param $connection
|
|
|
+ * @param $code
|
|
|
+ * @param $msg
|
|
|
+ */
|
|
|
+ public function onError($connection, $code, $msg)
|
|
|
+ {
|
|
|
+ echo "error $code $msg\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每个进程启动
|
|
|
+ * @param $worker
|
|
|
+ */
|
|
|
+ public function onWorkerStart($worker)
|
|
|
+ {
|
|
|
+ // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符
|
|
|
+ $inner_text_worker = new \Workerman\Worker('text://0.0.0.0:2347');
|
|
|
+ // $inner_text_worker->reusePort=true;
|
|
|
+ $inner_text_worker->onMessage = function ($connection, $buffer) {
|
|
|
+ // $data数组格式,里面有uid,表示向那个uid的页面推送数据
|
|
|
+ $data = json_decode($buffer, true);
|
|
|
+ $uid = $data['uid'];
|
|
|
+ // 通过workerman,向uid的页面推送数据
|
|
|
+ $ret = $this->sendMessageByUid($uid, $buffer);
|
|
|
+ // 返回推送结果
|
|
|
+ $connection->send($ret ? 'ok' : 'fail');
|
|
|
+ };
|
|
|
+ // ## 执行监听 ##
|
|
|
+ $inner_text_worker->listen();
|
|
|
+ Timer::add(10, function()use($worker){
|
|
|
+ $time_now = time();
|
|
|
+ foreach($worker->connections as $connection) {
|
|
|
+ // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
|
|
|
+ if (empty($connection->lastMessageTime)) {
|
|
|
+ $connection->lastMessageTime = $time_now;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $diff_time = $time_now - $connection->lastMessageTime;
|
|
|
+ $msg = '距离上次通话已经过去'.$diff_time.'秒';
|
|
|
+ $connection->send($msg);
|
|
|
+ // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
|
|
|
+ if ($time_now - $connection->lastMessageTime > $this->heartbeat_time) {
|
|
|
+ $connection->close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 向所有验证的用户推送数据
|
|
|
+ public function broadcast($message)
|
|
|
+ {
|
|
|
+ foreach($this->uidConnections as $connection)
|
|
|
+ {
|
|
|
+ $connection->send($message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 针对uid推送数据
|
|
|
+ public function sendMessageByUid($uid, $message)
|
|
|
+ {
|
|
|
+ if(isset($this->uidConnections[$uid]))
|
|
|
+ {
|
|
|
+ $connection = $this->uidConnections[$uid];
|
|
|
+ $connection->send($message);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|