/** * 获取在线状态,目前返回一个在线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; }
/** * 当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(); }
/** * 获取与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; }