imsocket.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. //print_r($arr);
  46. $connection->uid = $arr->uid;
  47. $this->connectionUid = $arr->uid;
  48. //保存uid到connection的映射,实现针对特定uid的推送
  49. $this->worker->uidConnections[$connection->uid]=$connection;
  50. if($arr->school_id){
  51. //如果是学校的话,返回一个老师的id给他。
  52. $tsql="SELECT u.user_id,u.user_type,u.real_name,u.nick_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";
  53. $resT=$db->query($tsql);
  54. if($resT->num_rows > 0) {
  55. $tempList=[];
  56. while($row = $resT->fetch_assoc()) {
  57. $temp['uid']= $row['user_id'];
  58. $temp['uname']= $row['real_name'];
  59. $temp['nick_name']= $row['nick_name'];
  60. $temp['utype']= $row['user_type'];
  61. if(isset($this->worker->uidConnections[$row['user_id']])){
  62. //是否在线,在线加权重
  63. $temp['w']=1;
  64. }else{
  65. $temp['w']=0;
  66. }
  67. $tempList[]=$temp;
  68. }
  69. //按权重随机返回
  70. $weight = 0;
  71. $tempdata = array ();
  72. foreach ($tempList as $one) {
  73. $weight += $one['w'];
  74. for ($i = 0; $i < $one['w']; $i++) {
  75. $tempdata[] = $one;
  76. }
  77. }
  78. $use = rand(0, $weight -1);
  79. $one = $tempdata[$use];
  80. $msg=['type'=>'bind','fansinfo'=>['uid'=>$one['uid'],'uname'=>$one['uname'],'nick_name'=>$one['nick_name']]];
  81. }else{
  82. $msg=['type'=>'bind','fansinfo'=>''];
  83. }
  84. }else{
  85. $msg=['type'=>'bind','fansinfo'=>''];
  86. }
  87. $connection->send(json_encode($msg));
  88. }
  89. //聊天
  90. if($arr->type=="text"){
  91. //print_r($arr);
  92. //先进库
  93. $insetSql="INSERT INTO yoshop_imchat (from_user_id,to_user_id,message,school_id,speciality_id,sendtime,chat_key,is_push)
  94. VALUES ('".$arr->from_user_id."','".$arr->to_user_id."','".$arr->msg."','".$arr->school_id."','".$arr->speciality_id."','".$arr->sendtime."','".$arr->chat_key."','1')";
  95. //保存数据
  96. $rs=$db->query($insetSql);
  97. $id=mysqli_insert_id($db);
  98. $temML['id']= $id;
  99. $temML['from_user_id']= $arr->from_user_id;
  100. $temML['to_user_id']= $arr->to_user_id;
  101. $temML['msg']= $arr->msg;
  102. $temML['school_id']= $arr->school_id;
  103. $temML['speciality_id']= $arr->speciality_id;
  104. $temML['chat_key']= $arr->chat_key;
  105. $temML['sendtime']= $arr->sendtime;
  106. $temML['type']= $arr->type;
  107. if(isset($this->worker->uidConnections[$arr->to_user_id])){
  108. $conn= $this->worker->uidConnections[$arr->to_user_id];
  109. $conn->send(json_encode($temML));
  110. }else{
  111. $conn= $this->worker->uidConnections[$arr->from_user_id];
  112. $conn->send(json_encode(['type'=>'down','msg'=>'对方不在线']));
  113. }
  114. }
  115. //在线更新已读消息
  116. if($arr->type=='readly'){
  117. $readSql="UPDATE yoshop_imchat SET is_push=0 WHERE id =".$arr->id;
  118. $db->query($readSql);
  119. }
  120. //获取聊天记录
  121. if($arr->type=="loadHistory"){
  122. $tfkey=$arr->tfkey;
  123. $lastMessageTimeStamp=$arr->lastMessageTimeStamp;
  124. $from_user_id=$arr->from_user_id;
  125. $conn2= $this->worker->uidConnections[$from_user_id];
  126. $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";
  127. $resML = $db->query($mlistSql);
  128. if($resML->num_rows > 0) {
  129. $msgList=[];
  130. //处理一下 未读变已读
  131. $push_id='';
  132. while($row = $resML->fetch_assoc()) {
  133. $temML['id']= $row['id'];
  134. $temML['from_user_id']= $row['from_user_id'];
  135. $temML['to_user_id']= $row['to_user_id'];
  136. $temML['message']= $row['message'];
  137. $temML['sendtime']= $row['sendtime'];
  138. if($row['is_push']==1 && $row['to_user_id']==$from_user_id){
  139. if(empty($push_id)){
  140. $push_id=$row['id'];
  141. }else{
  142. $push_id=$push_id .','.$row['id'];
  143. }
  144. }
  145. $msgList[]=$temML;
  146. }
  147. //更新未读变已读
  148. $upSql="UPDATE yoshop_imchat SET is_push=0 WHERE id IN(".$push_id.");";
  149. $db->query($upSql);
  150. $msg=['type'=>'loadHistory','mgList'=>$msgList];
  151. }else{
  152. $msg=['type'=>'loadHistory','mgList'=>''];
  153. }
  154. $conn2->send(json_encode($msg));
  155. }
  156. $db->close();
  157. }
  158. public function onClose($connection){
  159. unset($this->worker->uidConnnections[$this->connectionUid]);
  160. $connection->send(json_encode(['type'=>'all','msg'=>'用户'.$this->connectionUid.'已经下线']));
  161. $this->connectionUid='';
  162. }
  163. }