|
@@ -7,21 +7,24 @@ use MsgID;
|
|
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
require_once './msg.php';
|
|
|
+
|
|
|
class WebSocketClient
|
|
|
{
|
|
|
private \WebSocket\Client $socket;
|
|
|
private array $handlers = [];
|
|
|
private bool $isRunning = false;
|
|
|
private int $retryCount = 0;
|
|
|
+ private int $heartbeatInterval = 5; // 心跳间隔(秒)
|
|
|
|
|
|
public function __construct(
|
|
|
private string $url,
|
|
|
private array $options = [
|
|
|
'timeout' => 5,
|
|
|
- 'heartbeat_interval' => 30,
|
|
|
+ 'heartbeat_interval' => 5, // 默认5秒
|
|
|
'max_retries' => 10
|
|
|
]
|
|
|
) {
|
|
|
+ $this->heartbeatInterval = $this->options['heartbeat_interval'];
|
|
|
$this->connect();
|
|
|
}
|
|
|
|
|
@@ -48,7 +51,7 @@ class WebSocketClient
|
|
|
$binData = $binMsgId . $data;
|
|
|
$this->socket->binary($binData);
|
|
|
} catch (\Exception $e) {
|
|
|
- // $this->handleDisconnect($e);
|
|
|
+ $this->handleDisconnect($e);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -60,24 +63,41 @@ class WebSocketClient
|
|
|
|
|
|
$this->isRunning = true;
|
|
|
|
|
|
+ // 启动心跳子进程
|
|
|
+ $this->startHeartbeatProcess();
|
|
|
+
|
|
|
+ // 主进程持续监听消息
|
|
|
while ($this->isRunning) {
|
|
|
try {
|
|
|
- $this->sendHeartbeat();
|
|
|
- // 接收消息
|
|
|
$message = $this->socket->receive();
|
|
|
if ($message) {
|
|
|
$this->dispatchBinaryMessage($message);
|
|
|
}
|
|
|
- usleep(5); // 5ms 避免CPU过高使用
|
|
|
+ usleep(1000); // 1ms 避免CPU过高使用
|
|
|
} catch (\WebSocket\ConnectionException $e) {
|
|
|
error_log("ConnectionException 错误: " . $e->getMessage());
|
|
|
- // $this->handleDisconnect($e);
|
|
|
+ $this->handleDisconnect($e);
|
|
|
} catch (\Exception $e) {
|
|
|
error_log("Exception 错误: " . $e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private function startHeartbeatProcess(): void
|
|
|
+ {
|
|
|
+ $pid = pcntl_fork();
|
|
|
+ if ($pid == -1) {
|
|
|
+ throw new \RuntimeException("无法创建心跳子进程");
|
|
|
+ } elseif ($pid == 0) {
|
|
|
+ // 子进程:定时发送心跳
|
|
|
+ while ($this->isRunning) {
|
|
|
+ $this->sendHeartbeat();
|
|
|
+ sleep($this->heartbeatInterval);
|
|
|
+ }
|
|
|
+ exit(0); // 子进程退出
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private function dispatchBinaryMessage(string $binary): void
|
|
|
{
|
|
|
if (strlen($binary) < 2) {
|
|
@@ -104,7 +124,6 @@ class WebSocketClient
|
|
|
$hearbeat = new ReqHeartBeat();
|
|
|
$hearbeat->setMsg("ping");
|
|
|
$binaryData = $hearbeat->serializeToString();
|
|
|
- // 这里假设心跳消息ID为1,根据实际协议调整
|
|
|
$this->sendBinary(MsgID::REQHEARTBEAT, $binaryData);
|
|
|
} catch (\Exception $e) {
|
|
|
error_log("心跳发送失败: " . $e->getMessage());
|