Socket.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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', '6520'));
  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. // try{
  84. $this->ws->push($frame->fd, 'pong');
  85. return false;
  86. var_dump($frame->data);
  87. if ($frame->data == 'ping') {
  88. $this->ws->push($frame->fd, 'pong');
  89. return false;
  90. }
  91. // 消息处理
  92. $data = $frame->data ? json_decode($frame->data, true) : [];
  93. $op = isset($data['op']) ? $data['op'] : '';
  94. $userId = isset($data['from_uid'])? intval($data['from_uid']) : 0;
  95. $chatKey = isset($data['chat_key'])? trim($data['chat_key']) : '';
  96. $toUid = isset($data['to_uid'])? intval($data['to_uid']) : 0;
  97. if($userId && $frame->fd){
  98. $chatKey = $chatKey? $chatKey : getChatKey($userId, $toUid);
  99. RedisService::set("chats:bind:{$userId}", ['fd'=> $frame->fd, 'user_id'=> $userId,'chat_key'=>$chatKey], 86400);
  100. }
  101. if ($data) {
  102. switch ($op) {
  103. case 'chat': // 默认聊天
  104. $toUid = isset($data['to_uid']) ? intval($data['to_uid']) : 0;
  105. $fromUid = isset($data['from_uid']) ? intval($data['from_uid']) : 0;
  106. $messageType = isset($data['message_type']) ? $data['message_type'] : 1;
  107. if ($toUid <= 0 || $fromUid <= 0) {
  108. return false;
  109. }
  110. if (!ChatMessageService::make()->saveData($data)) {
  111. $data = ['message'=> lang(ChatMessageService::make()->getError())];
  112. $this->ws->push($frame->fd, json_encode($data, 256));
  113. return false;
  114. }
  115. $toInfo = MemberService::make()->getInfo($toUid);
  116. $fromInfo = MemberService::make()->getInfo($fromUid);
  117. $message = isset($data['message']) ? $data['message'] : '';
  118. $chatKey = getChatKey($fromUid, $toUid);
  119. $data = [
  120. 'type' => isset($data['type']) ? $data['type'] : 1,
  121. 'message_type' => $messageType,
  122. 'from_uid' => $fromUid,
  123. 'from_username' => isset($fromInfo['username']) ? $fromInfo['username'] : '客服',
  124. 'from_username_text' => isset($fromInfo['username']) ? format_account($fromInfo['username']) : '客服',
  125. 'to_uid' => isset($data['to_uid']) ? $data['to_uid'] : 0,
  126. 'to_username' => isset($toInfo['username']) ? $toInfo['username'] : '客服',
  127. 'to_username_text' => isset($toInfo['username']) ? format_account($toInfo['username']) : '客服',
  128. 'chat_key' => $chatKey,
  129. 'message' => $message,
  130. 'message_url' => $messageType == 2 && $message ? get_image_url($message) : '',
  131. 'create_time' => time(),
  132. 'time_text' => format_time(time()-1),
  133. 'is_read' => 1,
  134. 'status' => 1,
  135. ];
  136. $this->ws->push($frame->fd, json_encode($data, 256));
  137. $toBindData = RedisService::get("chats:bind:{$toUid}");
  138. $toFd = isset($toBindData['fd']) ? $toBindData['fd'] : 0;
  139. $toChatKey = isset($toBindData['chat_key']) ? $toBindData['chat_key'] : '';
  140. if ($toBindData && $toFd && $toChatKey == $chatKey) {
  141. $this->ws->push($toFd, json_encode($data, 256));
  142. }
  143. break;
  144. }
  145. $this->ws->push($frame->fd, json_encode(['message'=> $frame->data], 256));
  146. } else {
  147. $this->ws->push($frame->fd, json_encode(['message'=>'no data'], 256));
  148. }
  149. // } catch (\Exception $exception){
  150. // $this->ws->push($frame->fd, json_encode(['message'=> $exception->getMessage()], 256));
  151. // }
  152. }
  153. /**
  154. * 接收请求
  155. * @param $request
  156. * @param $response
  157. */
  158. public function request($request, $response)
  159. {
  160. }
  161. /**
  162. * 关闭连接
  163. * @param $ws
  164. * @param $fd
  165. */
  166. public function close($ws, $fd = '')
  167. {
  168. // var_dump($ws);
  169. echo '连接关闭:' . $fd . "\n";
  170. $this->ws->close($fd);
  171. }
  172. /**
  173. * 停止运行
  174. */
  175. public function stop($ws)
  176. {
  177. $this->ws->close();
  178. }
  179. }