protected function request($request) { $runDir = $this->service->getRunDir(); $port = (include $runDir . 'service-port.php'); $sockFile = $runDir . 'service-' . $port . '.sock'; $client = new Client(SWOOLE_UNIX_STREAM); $client->set(['open_length_check' => true, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4]); if (!@$client->connect($sockFile, 0, 20)) { return false; } $request = serialize($request); $client->send(pack('N', $length = strlen($request))); if ($length > 2097152) { foreach (str_split($request, 1048576) as $chunk) { $client->send($chunk); } } else { $client->send($request); } $response = $client->recv(); $client->close(); if ($response === false) { return false; } $length = unpack('N', $response)[1]; return unserialize(substr($response, -$length)); }
/** * 连接一个RPC服务器 * * @param $ip * @param $port * @return bool */ public function connect($ip, $port) { if ($this->__client) { @$this->__client->close(); $this->__client = null; } /** * @var RPC $rpc */ $this->__ip = $ip; $this->__port = $port; $this->__closeByServer = false; $rpc = $this->__rpc; $key = $rpc::_getRpcKey(); $client = new \Swoole\Client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC); $client->on('receive', function ($client, $data) use($key) { $arr = explode(Server::$EOF, $data); foreach ($arr as $item) { if ($item === '') { continue; } $tmp = @msgpack_unpack($item); if ($key) { $tmp = Server::decryption($tmp, $key); if (!$tmp) { \MyQEE\Server\Server::$instance->warn('rpc decryption data fail. data: ' . $item); continue; } } switch ($tmp->type) { case 'on': $event = $tmp->event; if (isset($this->__events[$event])) { # 回调执行 call_user_func_array($this->__events[$event], $tmp->args); } else { \MyQEE\Server\Server::$instance->warn("unknown rpc {$this->__rpc} event: {$event}"); } break; case 'close': $this->__closeByServer = true; $this->__client = null; break; default: \MyQEE\Server\Server::$instance->warn("unknown rpc type {$tmp->type}"); break; } } }); $client->on('connect', function ($client) { if (isset($this->__events['connect'])) { # 回调自定义的事件 call_user_func($this->__events['connect'], $client); } }); $client->on('close', function ($client) { $this->__client = null; \MyQEE\Server\Server::$instance->warn("rpc connection closed, {$this->__ip}:{$this->__port}."); if (!$this->isClosedByServer()) { # 不是被服务器强制关闭的则自动重新连接 $this->reconnect(); } if (isset($this->__events['close'])) { # 回调自定义的事件 call_user_func($this->__events['close'], $client); } }); $client->on('error', function ($client) { $this->__client = null; \MyQEE\Server\Server::$instance->warn("rpc connection({$this->__ip}:{$this->__port}) error: " . socket_strerror($client->errCode)); # 遇到错误则自动重连 swoole_timer_after(3000, function () { $this->reconnect(); }); if (isset($this->__events['error'])) { # 回调自定义的事件 call_user_func($this->__events['error'], $client); } }); $this->__client = $client; # 发心跳包 swoole_timer_tick(1000 * 60 * 5, function () { if ($this->__client && $this->__client->isConnected()) { $this->__client->send("" . Server::$EOF); } }); $this->__client->connect($ip, $port); return true; }