Esempio n. 1
0
 /**
  * 获取在线状态,目前返回一个在线client_id数组
  * @return array
  */
 public static function getOnlineStatus()
 {
     $gateway_data = GatewayProtocol::$empty;
     $gateway_data['cmd'] = GatewayProtocol::CMD_GET_ONLINE_STATUS;
     $gateway_buffer = GatewayProtocol::encode($gateway_data);
     if (isset(self::$businessWorker)) {
         $all_addresses = self::$businessWorker->getAllGatewayAddresses();
         if (empty($all_addresses)) {
             throw new \Exception('businessWorker::getAllGatewayAddresses return empty');
         }
     } else {
         $all_addresses = self::getAllGatewayAddressesFromRegister();
         if (empty($all_addresses)) {
             return array();
         }
     }
     $client_array = $status_data = $client_address_map = array();
     // 批量向所有gateway进程发送CMD_GET_ONLINE_STATUS命令
     foreach ($all_addresses as $address) {
         $client = stream_socket_client("udp://{$address}", $errno, $errmsg);
         if (strlen($gateway_buffer) === stream_socket_sendto($client, $gateway_buffer)) {
             $socket_id = (int) $client;
             $client_array[$socket_id] = $client;
             $client_address_map[$socket_id] = explode(':', $address);
         }
     }
     // 超时1秒
     $time_out = 1;
     $time_start = microtime(true);
     // 批量接收请求
     while (count($client_array) > 0) {
         $write = $except = array();
         $read = $client_array;
         if (@stream_select($read, $write, $except, $time_out)) {
             foreach ($read as $client) {
                 $socket_id = (int) $client;
                 $local_ip = ip2long($client_address_map[$socket_id][0]);
                 $local_port = $client_address_map[$socket_id][1];
                 // udp
                 $data = json_decode(stream_socket_recvfrom($client, 65535), true);
                 if ($data) {
                     foreach ($data as $connection_id) {
                         $status_data[] = Context::addressToClientId($local_ip, $local_port, $connection_id);
                     }
                 }
                 unset($client_array[$socket_id]);
             }
         }
         if (microtime(true) - $time_start > $time_out) {
             break;
         }
     }
     return $status_data;
 }
Esempio n. 2
0
 /**
  * 当gateway转发来数据时
  * @param TcpConnection $connection
  * @param mixed $data
  */
 public function onGatewayMessage($connection, $data)
 {
     // 上下文数据
     Context::$client_ip = $data['client_ip'];
     Context::$client_port = $data['client_port'];
     Context::$local_ip = $data['local_ip'];
     Context::$local_port = $data['local_port'];
     Context::$connection_id = $data['connection_id'];
     Context::$client_id = Context::addressToClientId($data['local_ip'], $data['local_port'], $data['connection_id']);
     // $_SERVER变量
     $_SERVER = array('REMOTE_ADDR' => $data['client_ip'], 'REMOTE_PORT' => $data['client_port'], 'GATEWAY_ADDR' => $data['local_ip'], 'GATEWAY_PORT' => $data['gateway_port'], 'GATEWAY_CLIENT_ID' => Context::$client_id);
     // 尝试解析session
     if ($data['ext_data'] != '') {
         $_SESSION = Context::sessionDecode($data['ext_data']);
     } else {
         $_SESSION = null;
     }
     // 备份一次$data['ext_data'],请求处理完毕后判断session是否和备份相等,不相等就更新session
     $session_str_copy = $data['ext_data'];
     $cmd = $data['cmd'];
     // 尝试执行Event::onConnection、Event::onMessage、Event::onClose
     try {
         switch ($cmd) {
             case GatewayProtocol::CMD_ON_CONNECTION:
                 Event::onConnect(Context::$client_id);
                 break;
             case GatewayProtocol::CMD_ON_MESSAGE:
                 Event::onMessage(Context::$client_id, $data['body']);
                 break;
             case GatewayProtocol::CMD_ON_CLOSE:
                 Event::onClose(Context::$client_id);
                 break;
         }
     } catch (\Exception $e) {
         $msg = 'client_id:' . Context::$client_id . "\tclient_ip:" . Context::$client_ip . "\n" . $e->__toString();
         $this->log($msg);
     }
     // 判断session是否被更改
     $session_str_now = $_SESSION !== null ? Context::sessionEncode($_SESSION) : '';
     if ($session_str_copy != $session_str_now) {
         \GatewayWorker\Lib\Gateway::updateSocketSession(Context::$client_id, $session_str_now);
     }
     Context::clear();
 }
 /**
  * 当gateway转发来数据时
  * @param TcpConnection $connection
  * @param mixed $data
  */
 public function onGatewayMessage($connection, $data)
 {
     // 上下文数据
     Context::$client_ip = $data['client_ip'];
     Context::$client_port = $data['client_port'];
     Context::$local_ip = $data['local_ip'];
     Context::$local_port = $data['local_port'];
     Context::$connection_id = $data['connection_id'];
     Context::$client_id = Context::addressToClientId($data['local_ip'], $data['local_port'], $data['connection_id']);
     // $_SERVER变量
     $_SERVER = array('REMOTE_ADDR' => long2ip($data['client_ip']), 'REMOTE_PORT' => $data['client_port'], 'GATEWAY_ADDR' => long2ip($data['local_ip']), 'GATEWAY_PORT' => $data['gateway_port'], 'GATEWAY_CLIENT_ID' => Context::$client_id);
     // 尝试解析session
     if ($data['ext_data'] != '') {
         $_SESSION = Context::sessionDecode($data['ext_data']);
     } else {
         $_SESSION = null;
     }
     // 备份一次$data['ext_data'],请求处理完毕后判断session是否和备份相等,不相等就更新session
     $session_str_copy = $data['ext_data'];
     $cmd = $data['cmd'];
     if ($this->processTimeout) {
         pcntl_alarm($this->processTimeout);
     }
     // 尝试执行Event::onConnection、Event::onMessage、Event::onClose
     switch ($cmd) {
         case GatewayProtocol::CMD_ON_CONNECTION:
             if ($this->_eventOnConnect) {
                 call_user_func($this->_eventOnConnect, Context::$client_id);
             }
             break;
         case GatewayProtocol::CMD_ON_MESSAGE:
             if ($this->_eventOnMessage) {
                 call_user_func($this->_eventOnMessage, Context::$client_id, $data['body']);
             }
             break;
         case GatewayProtocol::CMD_ON_CLOSE:
             if ($this->_eventOnClose) {
                 call_user_func($this->_eventOnClose, Context::$client_id);
             }
             break;
     }
     if ($this->processTimeout) {
         pcntl_alarm(0);
     }
     // 判断session是否被更改
     $session_str_now = $_SESSION !== null ? Context::sessionEncode($_SESSION) : '';
     if ($session_str_copy != $session_str_now) {
         \GatewayWorker\Lib\Gateway::updateSocketSession(Context::$client_id, $session_str_now);
     }
     Context::clear();
 }
Esempio n. 4
0
 /**
  * 获取与uid绑定的client_id列表
  * @param string $uid
  * @return array
  */
 public static function getClientIdByUid($uid)
 {
     $gateway_data = GatewayProtocol::$empty;
     $gateway_data['cmd'] = GatewayProtocol::CMD_GET_CLIENT_ID_BY_UID;
     $gateway_data['ext_data'] = $uid;
     $client_list = array();
     $all_buffer_array = self::getBufferFromAllGateway($gateway_data);
     foreach ($all_buffer_array as $local_ip => $buffer_array) {
         foreach ($buffer_array as $local_port => $buffer) {
             $connection_id_array = json_decode(rtrim($buffer), true);
             if ($connection_id_array) {
                 foreach ($connection_id_array as $connection_id) {
                     $client_list[] = Context::addressToClientId($local_ip, $local_port, $connection_id);
                 }
             }
         }
     }
     return $client_list;
 }