You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
5.2 KiB

4 years ago
  1. <?php
  2. namespace App\GatewayWorker;
  3. use GatewayWorker\Lib\Gateway;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Log;
  6. use App\Common\ReturnData;
  7. use App\Common\Helper;
  8. class Events
  9. {
  10. /**
  11. * 当businessWorker进程启动时触发,每个进程生命周期内都只会触发一次
  12. * 可以在这里为每一个businessWorker进程做一些全局初始化工作,例如设置定时器,初始化redis等连接等
  13. * 不要在onWorkerStart内执行长时间阻塞或者耗时的操作,这样会导致BusinessWorker无法及时与Gateway建立连接,造成应用异常
  14. * @param mixed $worker Worker对象
  15. */
  16. public static function onWorkerStart($businessWorker)
  17. {
  18. echo "onWorkerStart\r\n";
  19. }
  20. /**
  21. * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发的回调函数
  22. * onConnect事件仅仅代表客户端与gateway完成了TCP三次握手,这时客户端还没有发来任何数据,此时除了通过$_SERVER['REMOTE_ADDR']获得对方ip,没有其他可以鉴别客户端的数据或者信息,所以在onConnect事件里无法确认对方是谁。要想知道对方是谁,需要客户端发送鉴权数据,例如某个token或者用户名密码之类,在onMesssge里做鉴权
  23. * @param int $client_id
  24. */
  25. public static function onConnect($client_id)
  26. {
  27. echo "onConnect\r\n";
  28. Gateway::sendToClient($client_id, json_encode(['type' => 'onConnect', 'client_id' => $client_id]));
  29. }
  30. /**
  31. * 当客户端连接上gateway完成websocket握手时触发的回调函数
  32. * 注意:此回调只有gateway为websocket协议并且gateway没有设置onWebSocketConnect时才有效
  33. * @param int $client_id
  34. * @param mixed $data websocket握手时的http头数据,包含get、server等变量
  35. */
  36. public static function onWebSocketConnect($client_id, $data)
  37. {
  38. Log::info('onWebSocketConnect,client_id:' . $client_id . '-' . json_encode($data));
  39. echo "onWebSocketConnect\r\n";
  40. if (!isset($data['get']['token'])) {
  41. echo "closeClient\r\n";
  42. return Gateway::closeClient($client_id);
  43. }
  44. $access_token = $data['get']['token'];
  45. //通过client_id绑定用户ID
  46. $res = self::bing_client($client_id, ['access_token' => $access_token]);
  47. if ($res['code'] != ReturnData::SUCCESS) {
  48. return Gateway::sendToClient($client_id, json_encode($res));
  49. }
  50. Gateway::sendToClient($client_id, json_encode(ReturnData::create(ReturnData::SUCCESS)));
  51. }
  52. /**
  53. * 有消息时
  54. * @param int $client_id 发消息的client_id
  55. * @param mixed $message 完整的客户端请求数据,数据类型取决于Gateway所使用协议的decode方法返的回值类型
  56. */
  57. public static function onMessage($client_id, $data)
  58. {
  59. echo "onMessage\r\n";
  60. // Debug输出
  61. echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:" . json_encode($_SESSION) . " onMessage:" . $message . "\n";
  62. // data = {"type":"login", "uid":"666"}
  63. $data = json_decode($data, true);
  64. Log::info('onMessage,client_id:' . $client_id . '-' . json_encode($data));
  65. // 没有传消息类型视为非法请求,关闭连接
  66. if (!isset($data['type'])) {
  67. return Gateway::closeClient($client_id);
  68. }
  69. $uid = Gateway::getUidByClientId($client_id);
  70. // 判断绑定的UID为空,消息类型不是心跳视为非法请求,关闭连接
  71. if (empty($uid) && $data['type'] !== 'heart') {
  72. return Gateway::closeClient($client_id);
  73. }
  74. switch ($data['type']) {
  75. case 'heart': //心跳回复
  76. Gateway::sendToCurrentClient(json_encode(ReturnData::create(ReturnData::SUCCESS)));
  77. break;
  78. default:
  79. Gateway::sendToCurrentClient(json_encode(ReturnData::create(ReturnData::PARAMS_ERROR)));
  80. }
  81. }
  82. /**
  83. * 当客户端断开连接时
  84. * @param integer $client_id 断开连接的客户端client_id
  85. * @return void
  86. */
  87. public static function onClose($client_id)
  88. {
  89. // debug
  90. echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n";
  91. Log::info('Workerman close connection,client_id:' . $client_id);
  92. echo "onClose\r\n";
  93. }
  94. /**
  95. * 通过client_id绑定用户ID
  96. * @param int $client_id
  97. * @param mixed $message ['access_token']
  98. */
  99. public static function bing_client($client_id, $message)
  100. {
  101. if (!Gateway::isOnline($client_id)) {
  102. return ReturnData::create(ReturnData::PARAMS_ERROR, null, 'client_id错误');
  103. }
  104. //client_id绑定用户ID
  105. $token = DB::table('token')->where(['token' => $message['access_token']])->first();
  106. if (!$token) {
  107. return ReturnData::create(ReturnData::PARAMS_ERROR, null, '鉴权失败');
  108. }
  109. Gateway::bindUid($client_id, $token->uid);
  110. return ReturnData::create(ReturnData::SUCCESS);
  111. }
  112. }