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