Socket.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Services\ChatMessageService;
  4. use App\Services\Common\MemberService;
  5. use App\Services\RedisService;
  6. use Illuminate\Console\Command;
  7. class Socket extends Command
  8. {
  9. public $ws;
  10. /**
  11. * The name and signature of the console command.
  12. *
  13. * @var string
  14. */
  15. protected $signature = 'swoole:socket {op?}';
  16. /**
  17. * The console command description.
  18. *
  19. * @var string
  20. */
  21. protected $description = 'websocket ';
  22. /**
  23. * Create a new command instance.
  24. *
  25. * @return void
  26. */
  27. public function __construct()
  28. {
  29. parent::__construct();
  30. }
  31. /**
  32. * Execute the console command.
  33. *
  34. * @return mixed
  35. */
  36. public function handle()
  37. {
  38. $op = $this->argument('op');
  39. $op = $op ? $op : 'start';
  40. if ($op == 'start') {
  41. echo "socket start ...\n";
  42. $this->start();
  43. } else if ($op == 'stop') {
  44. echo "socket stop ...\n";
  45. $this->stop();
  46. }
  47. }
  48. /**
  49. * 运行
  50. */
  51. public function start()
  52. {
  53. //创建websocket服务器对象,监听0.0.0.0:7104端口
  54. $this->ws = new \swoole_websocket_server("0.0.0.0", env('SOCKET_PORT', '6420'));
  55. // $this->ws->set();
  56. //监听WebSocket连接打开事件
  57. $this->ws->on('open', [$this, 'open']);
  58. //监听WebSocket消息事件
  59. $this->ws->on('message', [$this, 'message']);
  60. //监听WebSocket主动推送消息事件
  61. $this->ws->on('request', [$this, 'request']);
  62. //监听WebSocket连接关闭事件
  63. $this->ws->on('close', [$this, 'close']);
  64. $this->ws->start();
  65. }
  66. /**
  67. * 建立连接
  68. * @param $ws
  69. * @param $request
  70. */
  71. public function open($ws, $request)
  72. {
  73. echo "连接成功:" . $request->fd . "\n";
  74. $this->ws->push($request->fd, json_encode(['message'=>'连接成功'], 256));
  75. }
  76. /**
  77. * 接收消息
  78. * @param $ws
  79. * @param $frame
  80. */
  81. public function message($ws, $frame)
  82. {
  83. if ($frame->data == 'ping') {
  84. $this->ws->push($frame->fd, 'pong');
  85. return false;
  86. }
  87. // 消息处理
  88. $data = $frame->data ? json_decode($frame->data, true) : [];
  89. $op = isset($data['op']) ? $data['op'] : '';
  90. $userId = isset($data['from_uid'])? intval($data['from_uid']) : 0;
  91. $chatKey = isset($data['chat_key'])? trim($data['chat_key']) : '';
  92. if($userId && $frame->fd){
  93. RedisService::set("chats:bind:{$userId}", ['fd'=> $frame->fd, 'user_id'=> $userId,'chat_key'=>$chatKey], 86400);
  94. }
  95. if ($data) {
  96. switch ($op) {
  97. case 'chat': // 默认聊天
  98. $toUid = isset($data['to_uid']) ? intval($data['to_uid']) : 0;
  99. $fromUid = isset($data['from_uid']) ? intval($data['from_uid']) : 0;
  100. $messageType = isset($data['message_type']) ? $data['message_type'] : 1;
  101. if ($toUid <= 0 || $fromUid <= 0) {
  102. return false;
  103. }
  104. if (!ChatMessageService::make()->saveData($data)) {
  105. $data = ['message'=> lang(ChatMessageService::make()->getError())];
  106. $this->ws->push($frame->fd, json_encode($data, 256));
  107. return false;
  108. }
  109. $toInfo = MemberService::make()->getInfo($toUid);
  110. $fromInfo = MemberService::make()->getInfo($fromUid);
  111. $message = isset($data['message']) ? $data['message'] : '';
  112. $chatKey = getChatKey($fromUid, $toUid);
  113. $data = [
  114. 'type' => isset($data['type']) ? $data['type'] : 1,
  115. 'message_type' => $messageType,
  116. 'from_uid' => $fromUid,
  117. 'from_userName' => isset($fromInfo['username']) ? format_account($fromInfo['username']) : '客服',
  118. 'to_uid' => isset($data['to_uid']) ? $data['to_uid'] : 0,
  119. 'to_userName' => isset($toInfo['username']) ? format_account($toInfo['username']) : '客服',
  120. 'chat_key' => $chatKey,
  121. 'message' => $message,
  122. 'message_url' => $messageType == 2 && $message ? get_image_url($message) : '',
  123. 'create_time' => time(),
  124. 'time_text' => date('m-d H:i'),
  125. 'is_read' => 1,
  126. 'status' => 1,
  127. ];
  128. $this->ws->push($frame->fd, json_encode($data, 256));
  129. $toBindData = RedisService::get("chats:bind:{$toUid}");
  130. $toFd = isset($toBindData['fd']) ? $toBindData['fd'] : 0;
  131. $toChatKey = isset($toBindData['chat_key']) ? $toBindData['chat_key'] : '';
  132. if ($toBindData && $toFd && $toChatKey == $chatKey) {
  133. $this->ws->push($toFd, json_encode($data, 256));
  134. }
  135. break;
  136. }
  137. } else {
  138. $this->ws->push($frame->fd, '{message:no data}');
  139. }
  140. }
  141. /**
  142. * 接收请求
  143. * @param $request
  144. * @param $response
  145. */
  146. public function request($request, $response)
  147. {
  148. }
  149. /**
  150. * 关闭连接
  151. * @param $ws
  152. * @param $fd
  153. */
  154. public function close($ws, $fd = '')
  155. {
  156. // var_dump($ws);
  157. echo '连接关闭:' . $fd . "\n";
  158. $this->ws->close($fd);
  159. }
  160. /**
  161. * 停止运行
  162. */
  163. public function stop($ws)
  164. {
  165. $this->ws->close();
  166. }
  167. }