GameClient.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. namespace App; // 添加命名空间
  3. require __DIR__.'/../generated/vendor/autoload.php';
  4. require_once __DIR__ . '/../vendor/autoload.php';
  5. require_once './msg.php';
  6. use App\WebSocketClient;
  7. use Common_pack\EnterHall;
  8. use Common_pack\ReqLogin;
  9. use Common_pack\ResEnterHall;
  10. use Common_pack\ResHeartBeat;
  11. use Common_pack\ResLogin;
  12. use Exception;
  13. use Google\Protobuf\Internal\Message;
  14. use MsgID;
  15. class GameClient {
  16. private ?WebSocketClient $client = null;
  17. private ?string $userId = null;
  18. private ?string $nikeName = null;
  19. private ?int $listenerPid = null;
  20. private bool $isRunning = false;
  21. public function start() {
  22. // $this->login();
  23. }
  24. public function close() {
  25. echo "命令调用了 close \n";
  26. }
  27. public function outGame(){
  28. echo "命令调用了 outGame \n";
  29. }
  30. public function login(string $account , string $password) {
  31. $loginReq = new ReqLogin();
  32. $loginReq->setAccount($account);
  33. $loginReq->setPassword($password);
  34. $binaryData = $loginReq->serializeToString();
  35. if (empty($binaryData)) {
  36. throw new Exception("序列化失败:返回空数据");
  37. }
  38. $options = [
  39. 'http' => [
  40. 'method' => 'POST',
  41. 'header' => implode("\r\n", [
  42. 'Content-Type: application/x-protobuf',
  43. 'Accept: */*',
  44. 'Accept-Language: zh-CN,zh;q=0.9',
  45. // 'Connection: keep-alive',
  46. 'Connection: close',
  47. 'Referer: http://localhost:7456/'
  48. ]),
  49. 'content' => $binaryData,
  50. 'timeout' => 10,
  51. 'ignore_errors' => false
  52. ]
  53. ];
  54. try {
  55. echo "登陆请求时间:";
  56. echo date('Y-m-d H:i:s');
  57. echo "\n";
  58. $url = 'http://120.76.130.29:8080/ReqLogin';
  59. $context = stream_context_create($options);
  60. $response = file_get_contents($url, false, $context);
  61. if ($response === false) {
  62. throw new Exception("请求失败: " . error_get_last()['message']);
  63. }
  64. if (strpos($response, '404 page not found') !== false) {
  65. throw new Exception("API端点不存在(404),请检查URL: " . $url);
  66. }
  67. echo "登陆响应时间:";
  68. echo date('Y-m-d H:i:s');
  69. echo "\n";
  70. $userResponse = new ResLogin();
  71. $userResponse->mergeFromString($response);
  72. if ($userResponse->getErrMsg() !== null) {
  73. throw new Exception("登录失败: " . $userResponse->getErrMsg()->getMessage());
  74. }
  75. echo "登录成功!\n";
  76. echo "用户ID: " . $userResponse->getUserId() . "\n";
  77. echo "昵称: " . $userResponse->getNikeName() . "\n";
  78. $this->userId = $userResponse->getUserId();
  79. $this->nikeName = $userResponse->getNikeName();
  80. $this->initWebSocketConnection();
  81. echo "是否成功获取信息: " .$userResponse->hasUserInfo() . "\n";
  82. if ($userResponse->hasUserInfo()) {
  83. $this->enterHall($userResponse->getUserInfo()->getUserId());
  84. $this->startListening();
  85. }
  86. } catch (Exception $e) {
  87. echo $e->getMessage() . "\n";
  88. exit(1);
  89. }
  90. }
  91. private function initWebSocketConnection() {
  92. // wss://leaf.ktle.top
  93. $this->client = new WebSocketClient('ws://localhost:3653');
  94. $this->client->on(MsgID::RESENTERHALL, function($binaryData) {
  95. $response = new ResEnterHall();
  96. $response->mergeFromString($binaryData);
  97. echo "成功进入大厅!\n";
  98. });
  99. $this->client->on(MsgID::RESHEARTBEAT, function($binaryData) {
  100. $response = new ResHeartBeat();
  101. $response->mergeFromString($binaryData);
  102. echo "心跳:".$response->getMsg();
  103. echo "\n";
  104. });
  105. }
  106. private function startListening() {
  107. if (!$this->client) {
  108. throw new Exception("WebSocket连接未建立");
  109. }
  110. if ($this->listenerPid !== null) {
  111. return; // 已经启动监听
  112. }
  113. echo "开始监听WebSocket消息...\n";
  114. $pid = pcntl_fork();
  115. if ($pid == -1) {
  116. throw new Exception("无法创建子进程");
  117. } elseif ($pid == 0) {
  118. // 子进程:持续监听WebSocket
  119. $this->isRunning = true;
  120. $this->client->startListening();
  121. exit(0);
  122. } else {
  123. // 父进程记录子进程ID
  124. $this->listenerPid = $pid;
  125. $this->isRunning = true;
  126. }
  127. }
  128. public function isRunning(): bool {
  129. return $this->isRunning;
  130. }
  131. private function enterHall($userId) {
  132. if (!$this->client) {
  133. throw new Exception("WebSocket连接未建立");
  134. }
  135. $enterHall = new EnterHall();
  136. $enterHall->setUserId($userId);
  137. $binaryData = $enterHall->serializeToString();
  138. $this->client->sendBinary(MsgID::ENTERHALL, $binaryData);
  139. echo "已发送进入大厅请求\n";
  140. }
  141. }
  142. // 启动客户端
  143. // $gameClient = new GameClient();
  144. // $gameClient->start();