WebSocketService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. namespace App\Services;
  3. use App\Module\Base;
  4. use App\Module\Chat;
  5. use Cache;
  6. use DB;
  7. use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
  8. use Swoole\Http\Request;
  9. use Swoole\WebSocket\Frame;
  10. use Swoole\WebSocket\Server;
  11. /**
  12. * @see https://wiki.swoole.com/#/start/start_ws_server
  13. */
  14. class WebSocketService implements WebSocketHandlerInterface
  15. {
  16. /**
  17. * 声明没有参数的构造函数
  18. * WebSocketService constructor.
  19. */
  20. public function __construct()
  21. {
  22. }
  23. /**
  24. * 连接建立时触发
  25. * @param Server $server
  26. * @param Request $request
  27. */
  28. public function onOpen(Server $server, Request $request)
  29. {
  30. $to = $request->fd;
  31. if (!isset($request->get['token'])) {
  32. $server->push($to, Base::array2json([
  33. 'messageType' => 'error',
  34. 'type' => 'user',
  35. 'sender' => null,
  36. 'target' => null,
  37. 'content' => [
  38. 'error' => '参数错误'
  39. ],
  40. 'time' => Base::time()
  41. ]));
  42. $server->close($to);
  43. self::forgetUser($to);
  44. return;
  45. }
  46. //
  47. $token = $request->get['token'];
  48. $cacheKey = "ws-token:" . md5($token);
  49. $username = Cache::remember($cacheKey, now()->addSeconds(1), function () use ($token) {
  50. list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($token) . "@@@@");
  51. if (intval($id) > 0 && intval($timestamp) + 2592000 > Base::time()) {
  52. if (DB::table('users')->where(['id' => $id, 'username' => $username, 'encrypt' => $encrypt])->exists()) {
  53. return $username;
  54. }
  55. }
  56. return null;
  57. });
  58. if (empty($username)) {
  59. Cache::forget($cacheKey);
  60. $server->push($to, Base::array2json([
  61. 'messageType' => 'error',
  62. 'type' => 'user',
  63. 'sender' => null,
  64. 'target' => null,
  65. 'content' => [
  66. 'error' => '会员不存在',
  67. ],
  68. 'time' => Base::time()
  69. ]));
  70. $server->close($to);
  71. self::forgetUser($to);
  72. return;
  73. }
  74. //
  75. self::saveUser($to, $username);
  76. $server->push($to, Base::array2json([
  77. 'messageType' => 'open',
  78. 'type' => 'user',
  79. 'sender' => null,
  80. 'target' => null,
  81. 'content' => [
  82. 'swid' => $to,
  83. ],
  84. 'time' => Base::time()
  85. ]));
  86. }
  87. /**
  88. * 收到消息时触发
  89. * @param Server $server
  90. * @param Frame $frame
  91. */
  92. public function onMessage(Server $server, Frame $frame)
  93. {
  94. $data = Base::json2array($frame->data);
  95. $feedback = [
  96. 'status' => 1,
  97. 'message' => '',
  98. ];
  99. switch ($data['type']) {
  100. case 'user':
  101. $to = self::name2fd($data['target']);
  102. if ($to) {
  103. $res = Chat::saveMessage(self::fd2name($frame->fd), $data['target'], $data['content']);
  104. if (Base::isError($res)) {
  105. $feedback = [
  106. 'status' => 0,
  107. 'message' => $res['msg'],
  108. ];
  109. } else {
  110. $data['content']['id'] = $res['data']['id'];
  111. $server->push($to, Base::array2json($data));
  112. $feedback['message'] = $res['data']['id'];
  113. }
  114. } else {
  115. $feedback = [
  116. 'status' => 0,
  117. 'message' => '账号不存在!',
  118. ];
  119. }
  120. break;
  121. case 'all':
  122. foreach (self::getUsersAll() as $user) {
  123. $data['target'] = $user['username'];
  124. $server->push($user['wsid'], Base::array2json($data));
  125. }
  126. break;
  127. }
  128. if ($data['messageId']) {
  129. $server->push($frame->fd, Base::array2json([
  130. 'messageType' => 'feedback',
  131. 'messageId' => $data['messageId'],
  132. 'type' => 'user',
  133. 'sender' => null,
  134. 'target' => null,
  135. 'content' => $feedback,
  136. 'time' => Base::time()
  137. ]));
  138. }
  139. }
  140. /**
  141. * 关闭连接时触发
  142. * @param Server $server
  143. * @param $fd
  144. * @param $reactorId
  145. */
  146. public function onClose(Server $server, $fd, $reactorId)
  147. {
  148. self::forgetUser($fd);
  149. }
  150. /** ****************************************************************************** */
  151. /** ****************************************************************************** */
  152. /** ****************************************************************************** */
  153. /**
  154. * 缓存用户信息
  155. * @param $fd
  156. * @param $username
  157. */
  158. public static function saveUser($fd, $username)
  159. {
  160. DB::table('users')->where('wsid', $fd)->update(['wsid' => 0]);
  161. DB::table('users')->where('username', $username)->update(['wsid' => $fd]);
  162. }
  163. /**
  164. * 清除用户缓存
  165. * @param $fd
  166. */
  167. public static function forgetUser($fd)
  168. {
  169. DB::table('users')->where('wsid', $fd)->update(['wsid' => 0]);
  170. }
  171. /**
  172. * 获取当前用户
  173. * @return array|string
  174. */
  175. public static function getUsersAll()
  176. {
  177. return Base::DBC2A(DB::table('users')->select(['wsid', 'username'])->where('wsid', '>', 0)->get());
  178. }
  179. /**
  180. * @param $fd
  181. * @return mixed
  182. */
  183. public static function fd2name($fd)
  184. {
  185. return DB::table('users')->select(['username'])->where('wsid', $fd)->value('username');
  186. }
  187. /**
  188. * @param $username
  189. * @return mixed
  190. */
  191. public static function name2fd($username)
  192. {
  193. return DB::table('users')->select(['wsid'])->where('username', $username)->value('wsid');
  194. }
  195. }