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