GameClient.php 6.2 KB

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