start_io.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. use Workerman\Worker;
  3. use Workerman\WebServer;
  4. use Workerman\Lib\Timer;
  5. use PHPSocketIO\SocketIO;
  6. include __DIR__ . '/vendor/autoload.php';
  7. // 全局数组保存uid在线数据
  8. $uidConnectionMap = array();
  9. // 记录最后一次广播的在线用户数
  10. $last_online_count = 0;
  11. // 记录最后一次广播的在线页面数
  12. $last_online_page_count = 0;
  13. // PHPSocketIO服务
  14. $sender_io = new SocketIO(2120);
  15. // 客户端发起连接事件时,设置连接socket的各种事件回调
  16. $sender_io->on('connection', function($socket){
  17. // 当客户端发来登录事件时触发
  18. $socket->on('login', function ($uid)use($socket){
  19. global $uidConnectionMap, $last_online_count, $last_online_page_count;
  20. // 已经登录过了
  21. if(isset($socket->uid)){
  22. return;
  23. }
  24. // 更新对应uid的在线数据
  25. $uid = (string)$uid;
  26. if(!isset($uidConnectionMap[$uid]))
  27. {
  28. $uidConnectionMap[$uid] = 0;
  29. }
  30. // 这个uid有++$uidConnectionMap[$uid]个socket连接
  31. ++$uidConnectionMap[$uid];
  32. // 将这个连接加入到uid分组,方便针对uid推送数据
  33. $socket->join($uid);
  34. $socket->uid = $uid;
  35. // 更新这个socket对应页面的在线数据
  36. //$socket->emit('update_online_count', "当前<b>{$last_online_count}</b>人在线,共打开<b>{$last_online_page_count}</b>个页面");
  37. });
  38. // 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
  39. $socket->on('disconnect', function () use($socket) {
  40. if(!isset($socket->uid))
  41. {
  42. return;
  43. }
  44. //$url = 'http://47.104.128.143/cron/offline/index?uid='.$socket->uid;
  45. //file_get_contents($url);
  46. $param = '/cron/offline/index?uid='.$socket->uid;
  47. $fp = fsockopen("47.104.128.143", 80, $errno, $errstr, 30);
  48. if (!$fp) {
  49. echo "$errstr ($errno)<br />\n";
  50. } else {
  51. $out = "GET $param HTTP/1.1\r\n";
  52. $out .= "Host: 47.104.128.143\r\n";
  53. $out .= "Connection: Close\r\n\r\n";
  54. fwrite($fp, $out);
  55. #while (!feof($fp)) {
  56. #echo fgets($fp, 128);
  57. #}
  58. fclose($fp);
  59. }
  60. global $uidConnectionMap, $sender_io;
  61. // 将uid的在线socket数减一
  62. if(--$uidConnectionMap[$socket->uid] <= 0)
  63. {
  64. unset($uidConnectionMap[$socket->uid]);
  65. }
  66. });
  67. });
  68. // 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
  69. $sender_io->on('workerStart', function(){
  70. // 监听一个http端口
  71. $inner_http_worker = new Worker('http://0.0.0.0:2121');
  72. // 当http客户端发来数据时触发
  73. $inner_http_worker->onMessage = function($http_connection, $data){
  74. global $uidConnectionMap;
  75. $_POST = $_POST ? $_POST : $_GET;
  76. // 推送数据的url格式 type=publish&to=uid&content=xxxx
  77. switch(@$_POST['type']){
  78. case 'publish':
  79. global $sender_io;
  80. $to = @$_POST['to'];
  81. //$_POST['content'] = htmlspecialchars(@$_POST['content']);
  82. // 有指定uid则向uid所在socket组发送数据
  83. if($to){
  84. $sender_io->to($to)->emit('new_msg', $_POST['content']);
  85. // 否则向所有uid推送数据
  86. }else{
  87. $sender_io->emit('new_msg', @$_POST['content']);
  88. }
  89. // http接口返回,如果用户离线socket返回fail
  90. if($to && !isset($uidConnectionMap[$to])){
  91. return $http_connection->send('offline');
  92. }else{
  93. return $http_connection->send('ok');
  94. }
  95. break;
  96. case 'online':
  97. return $http_connection->send(json_encode($uidConnectionMap));
  98. break;
  99. }
  100. return $http_connection->send('fail');
  101. };
  102. // 执行监听
  103. $inner_http_worker->listen();
  104. // 一个定时器,定时向所有uid推送当前uid在线数及在线页面数
  105. Timer::add(1, function(){
  106. global $uidConnectionMap, $sender_io, $last_online_count, $last_online_page_count;
  107. $online_count_now = count($uidConnectionMap);
  108. $online_page_count_now = array_sum($uidConnectionMap);
  109. // 只有在客户端在线数变化了才广播,减少不必要的客户端通讯
  110. if($last_online_count != $online_count_now || $last_online_page_count != $online_page_count_now)
  111. {
  112. //$sender_io->emit('update_online_count', "当前<b>{$online_count_now}</b>人在线,共打开<b>{$online_page_count_now}</b>个页面");
  113. $last_online_count = $online_count_now;
  114. $last_online_page_count = $online_page_count_now;
  115. }
  116. });
  117. });
  118. if(!defined('GLOBAL_START'))
  119. {
  120. Worker::runAll();
  121. }