imsocket.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. namespace app\api\imsocket;
  3. use think\worker\Server;
  4. use Workerman\Lib\Timer;
  5. use workerman\workerman;
  6. define('HEARTBEAT_TIME', 45);
  7. class imsocket extends Server
  8. {
  9. protected $socket = 'websocket://0.0.0.0:6541';
  10. protected $uidConnnections = array();
  11. protected $connectionUid;
  12. public function __construct()
  13. {
  14. parent::__construct();
  15. }
  16. public function onConnect($connection){
  17. $msg=['type'=>'conn','msg'=>'连接服务器成功'];
  18. $connection->send(json_encode($msg));
  19. }
  20. // public function onWorkerStart($worker){
  21. // //设置一个每50秒运转一次的定时器
  22. // Timer::add(50, function()use($worker){
  23. // $time_now = time();
  24. // foreach($worker->connections as $connection) {
  25. // // connection还没收到过音讯,则lastMessageTime设置为当前时时间
  26. // if (empty($connection->lastConnTime)) {
  27. // $connection->lastConnTime = $time_now;
  28. // continue;
  29. // }
  30. // if ($time_now - $connection->lastConnTime > HEARTBEAT_TIME) {
  31. // $connection->close();
  32. // }
  33. // }
  34. // });
  35. // }
  36. public function onMessage($connection,$data)
  37. {
  38. //给connection暂时设置一个lastConnTime属性,用来纪录上次收到音讯的时间
  39. $connection->lastConnTime = time();
  40. $arr = json_decode($data);
  41. $db = new \mysqli('47.112.222.163','nn2022060401','RL2rpdKdKicikFBx','nn2022060401','3306');
  42. $db->set_charset('utf8');
  43. //绑定用户
  44. if($arr->type == "bind" && !isset($connection->uid)){
  45. $connection->uid = $arr->uid;
  46. $this->connectionUid = $arr->uid;
  47. //保存uid到connection的映射,实现针对特定uid的推送
  48. $this->worker->uidConnections[$connection->uid]=$connection;
  49. if($arr->school_id){
  50. //如果是学校的话,返回一个老师的id给他。
  51. $tsql="SELECT u.user_id,u.user_type,u.real_name FROM yoshop_user_info i JOIN yoshop_user u ON i.user_id = u.user_id WHERE u.user_type=3 AND u.is_delete=0 AND i.school_id=".$arr->school_id." AND i.status=1";
  52. $resT=$db->query($tsql);
  53. if($resT->num_rows > 0) {
  54. $tempList=[];
  55. while($row = $resT->fetch_assoc()) {
  56. $temp['uid']= $row['user_id'];
  57. $temp['uname']= $row['real_name'];
  58. $temp['utype']= $row['user_type'];
  59. if(isset($this->worker->uidConnections[$row['user_id']])){
  60. //是否在线,在线加权重
  61. $temp['w']=1;
  62. }else{
  63. $temp['w']=0;
  64. }
  65. $tempList[]=$temp;
  66. }
  67. //按权重随机返回
  68. $weight = 0;
  69. $tempdata = array ();
  70. foreach ($tempList as $one) {
  71. $weight += $one['w'];
  72. for ($i = 0; $i < $one['w']; $i++) {
  73. $tempdata[] = $one;
  74. }
  75. }
  76. $use = rand(0, $weight -1);
  77. $one = $tempdata[$use];
  78. $msg=['type'=>'bind','fansinfo'=>['uid'=>$one['uid'],'uname'=>$one['uname']]];
  79. }else{
  80. $msg=['type'=>'bind','fansinfo'=>''];
  81. }
  82. }else{
  83. $msg=['type'=>'bind','fansinfo'=>''];
  84. }
  85. $connection->send(json_encode($msg));
  86. }
  87. //聊天
  88. if($arr->type=="text"){
  89. //先进库
  90. $insetSql="INSERT INTO yoshop_imchat (from_user_id,to_user_id,message,school_id,speciality_id,sendtime,chat_key,is_push)
  91. VALUES ('".$arr->from_user_id."','".$arr->to_user_id."','".$arr->msg."','".$arr->school_id."','".$arr->speciality_id."','".$arr->sendtime."','".$arr->chat_key."','1')";
  92. //保存数据
  93. $rs=$db->query($insetSql);
  94. $id=mysqli_insert_id($db);
  95. $temML['id']= $id;
  96. $temML['from_user_id']= $arr->from_user_id;
  97. $temML['to_user_id']= $arr->to_user_id;
  98. $temML['msg']= $arr->msg;
  99. $temML['school_id']= $arr->school_id;
  100. $temML['speciality_id']= $arr->speciality_id;
  101. $temML['chat_key']= $arr->chat_key;
  102. $temML['sendtime']= $arr->sendtime;
  103. $temML['type']= $arr->type;
  104. if(isset($this->worker->uidConnections[$arr->to_user_id])){
  105. $conn= $this->worker->uidConnections[$arr->to_user_id];
  106. $conn->send(json_encode($temML));
  107. }else{
  108. $conn= $this->worker->uidConnections[$arr->from_user_id];
  109. $conn->send(json_encode(['type'=>'down','msg'=>'对方不在线']));
  110. }
  111. }
  112. //在线更新已读消息
  113. if($arr->type=='readly'){
  114. $readSql="UPDATE yoshop_imchat SET is_push=0 WHERE id =".$arr->id;
  115. $db->query($readSql);
  116. }
  117. //获取聊天记录
  118. if($arr->type=="loadHistory"){
  119. $tfkey=$arr->tfkey;
  120. $lastMessageTimeStamp=$arr->lastMessageTimeStamp;
  121. $from_user_id=$arr->from_user_id;
  122. $conn2= $this->worker->uidConnections[$from_user_id];
  123. $mlistSql="select id,from_user_id,to_user_id,message,sendtime,is_push from yoshop_imchat where chat_key=$tfkey and sendtime < $lastMessageTimeStamp order by sendtime desc limit 10";
  124. $resML = $db->query($mlistSql);
  125. if($resML->num_rows > 0) {
  126. $msgList=[];
  127. //处理一下 未读变已读
  128. $push_id='';
  129. while($row = $resML->fetch_assoc()) {
  130. $temML['id']= $row['id'];
  131. $temML['from_user_id']= $row['from_user_id'];
  132. $temML['to_user_id']= $row['to_user_id'];
  133. $temML['message']= $row['message'];
  134. $temML['sendtime']= $row['sendtime'];
  135. if($row['is_push']==1 && $row['to_user_id']==$from_user_id){
  136. if(empty($push_id)){
  137. $push_id=$row['id'];
  138. }else{
  139. $push_id=$push_id .','.$row['id'];
  140. }
  141. }
  142. $msgList[]=$temML;
  143. }
  144. //更新未读变已读
  145. $upSql="UPDATE yoshop_imchat SET is_push=0 WHERE id IN(".$push_id.");";
  146. $db->query($upSql);
  147. $msg=['type'=>'loadHistory','mgList'=>$msgList];
  148. }else{
  149. $msg=['type'=>'loadHistory','mgList'=>''];
  150. }
  151. $conn2->send(json_encode($msg));
  152. }
  153. $db->close();
  154. }
  155. public function onClose($connection){
  156. unset($this->worker->uidConnnections[$this->connectionUid]);
  157. $connection->send(json_encode(['type'=>'all','msg'=>'用户'.$this->connectionUid.'已经下线']));
  158. $this->connectionUid='';
  159. }
  160. }