|  | @@ -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;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |