Files
2026-04-23 18:25:35 +08:00

111 lines
4.5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\push\controller;
use Workerman\Worker;
use PHPSocketIO\SocketIO;
class Push
{
public function index()
{
// 全局数组保存uid在线数据
$uidConnectionMap = [];
// 记录最后一次广播的在线用户数
$last_online_count = 0;
// 记录最后一次广播的在线页面数
$last_online_page_count = 0;
// 模拟推送的数值(这里可以从数据库或其他地方获取)
$push_value = 0;
// PHPSocketIO服务
$sender_io = new SocketIO(2120);
// 定时任务每3秒更新一次数值并推送给所有客户端
\Workerman\Lib\Timer::add(3, function() use (&$push_value, $sender_io) {
// 模拟数值变化(可以替换为实际的业务逻辑)
$push_value = rand(100, 1000);
// 向所有连接的客户端推送数值
$sender_io->emit('push_value', ['value' => $push_value]);
});
// 客户端发起连接事件时设置连接socket的各种事件回调
$sender_io->on('connection', function($socket) use (&$push_value){
// 当客户端发来登录事件时触发
$socket->on('login', function ($uid)use($socket){
global $uidConnectionMap, $last_online_count, $last_online_page_count;
// 已经登录过了
if(isset($socket->uid)){
return;
}
// 更新对应uid的在线数据
$uid = (string)$uid;
if(!isset($uidConnectionMap[$uid]))
{
$uidConnectionMap[$uid] = 0;
}
// 这个uid有++$uidConnectionMap[$uid]个socket连接
++$uidConnectionMap[$uid];
// 将这个连接加入到uid分组方便针对uid推送数据
$socket->join($uid);
$socket->uid = $uid;
// 更新这个socket对应页面的在线数据
$socket->emit('update_online_count', "当前<b>{$last_online_count}</b>人在线,共打开<b>{$last_online_page_count}</b>个页面");
});
// 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
$socket->on('disconnect', function () use($socket) {
if(!isset($socket->uid))
{
return;
}
global $uidConnectionMap, $sender_io;
// 将uid的在线socket数减一
if(--$uidConnectionMap[$socket->uid] <= 0)
{
unset($uidConnectionMap[$socket->uid]);
}
});
});
// 当$sender_io启动后监听一个http端口通过这个端口可以给任意uid或者所有uid推送数据
$sender_io->on('workerStart', function()use ($sender_io){
// 监听一个http端口
$inner_http_worker = new Worker('http://0.0.0.0:2121');
// 当http客户端发来数据时触发
$inner_http_worker->onMessage = function($http_connection, $data)use ($sender_io){
global $uidConnectionMap;
$msgContent = $_POST?$_POST:$_GET;
// 推送数据的url格式 type=publish&to=uid&content=xxxx
switch(@$msgContent['type']){
case 'publish':
$to = $msgContent['to'];
// 有指定uid则向uid所在socket组发送数据
if($to){
$sender_io->to($to)->emit('newMsg', $msgContent['content']);
// 否则向所有uid推送数据
}else{
$sender_io->emit('newMsg', $msgContent['content']);
}
// http接口返回如果用户离线socket返回fail
if($to && !isset($uidConnectionMap[$to])){
return $http_connection->send('offline');
}else{
return $http_connection->send('ok');
}
}
// $sender_io->to(1)->emit('newMsg', '呀死啦累');
return $http_connection->send('fail');
};
// 执行监听
$inner_http_worker->listen();
});
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
}
}