一. 测试服务端
//测试服务端
public function testServer()
{
$server = new Server('192.168.0.144', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP);
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'text/plain');
$response->end("Hello, Swoole!");
});
$server->start();
}
二. 服务端 , 本服务端使用 swoole-v2.2.0, 推送主代码
<?php
namespace app\index\controller;
use think\Db;
use Swoole\Http\Server;
use Swoole\WebSocket\Server as ServerSocket;
use Swoole\Timer;
//启动服务端,将满足条件的数据推送
public function notificationServer()
{
$server = new ServerSocket('192.168.0.144', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP);
$timerCallback = function () use ($server) {
$results = Db::name('scores')->where('uid', '=', 9)->find();
$score = $results['score'];
// 判断分数是否达到60分
if ($score >= 60) {
// 向所有连接的客户端发送通知和成绩单
$message = "您的成绩已经合格,请去考试中心打印成绩单";
} else {
$message = "您的成绩不合格,请下次继续努力呢";
}
foreach ($server->connections as $fd) {
$server->push($fd, $message);
}
};
$server->on('open', function ($server, $request) use ($timerCallback) {
echo "WebSocket连接建立成功\n";
// 启动定时器,每隔5秒触发一次
$timerId = Timer::tick(500, $timerCallback);
$server->wsTimerId = $timerId;
});
$server->on('message', function ($server, $frame) {
echo "收到消息:{$frame->data}\n";
// $server->push($frame->fd, "服务器收到了你的消息:{$frame->data}");
});
$server->on('close', function ($server, $fd) {
echo "WebSocket连接关闭\n";
// 清除定时器
Timer::clear($server->wsTimerId);
});
$server->start();
}
三.启动服务端
php public/index.php index/index/notificationServer > /dev/null 2>&1 &
或者
php public/index.php index/index/notificationServer
可以用路由
四 数据库
五.客户单web代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Client</title>
<!-- 导入jQuery库 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<style>
.red-bubble {
display: none; /* 初始时隐藏气泡 */
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 10px;
background-color: red;
color: white;
font-weight: bold;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="redBubble" class="red-bubble"></div>
<script>
var socket = new WebSocket("ws://192.168.0.144:9501");
var redBubble = $("#redBubble");
socket.onopen = function() {
console.log("WebSocket connection established.");
};
// socket.onopen = function() {
// console.log("WebSocket connection established.");
// // 连接建立后发送消息
// var messageToSend = "Hello, server!";
// socket.send(messageToSend);
// };
socket.onmessage = function(event) {
console.log(event);
var message = event.data;
console.log("Received message: " + message);
// 显示气泡并缓慢显示
redBubble.text(message).fadeIn("slow");
// 5秒后缓慢消失
setTimeout(function() {
redBubble.fadeOut("slow");
}, 5000);
};
socket.onclose = function(event) {
console.log("WebSocket connection closed with code: " + event.code);
};
</script>
</body>
</html>
效果
ps:若要实现指定用户推送请参考下面的代码, 通过 session(‘uid’) 获取到当前用户的用户ID,并将其与连接标识进行映射。在收到消息时,获取目标用户的用户ID,并根据用户ID找到对应的连接标识,然后向该连接标识对应的用户推送消息。
use Swoole\WebSocket\Server;
// 创建全局数组用于存储连接标识与用户ID的映射关系
$connections = [];
$server = new Server('0.0.0.0', 9501);
$server->on('open', function (Server $server, $request) use (&$connections) {
// 获取用户ID
$userId = session('uid');
// 将连接标识与用户ID的映射关系保存到全局数组中
$connections[$request->fd] = $userId;
echo "用户ID为{$userId}的用户已连接\n";
});
$server->on('message', function (Server $server, $frame) use (&$connections) {
echo "收到消息:{$frame->data}\n";
// 获取要推送的用户ID
$targetUserId = session('uid');
// 通过用户ID找到对应的连接标识
foreach ($connections as $fd => $userId) {
if ($userId === $targetUserId) {
// 向指定用户推送消息
$server->push($fd, $message);
}
}
});
$server->on('close', function (Server $server, $fd) use (&$connections) {
// 从数组中移除断开连接的映射关系
unset($connections[$fd]);
echo "连接标识为{$fd}的用户已断开连接\n";
});
$server->start();
在该示例中,我们通过 session(‘uid’) 获取到当前用户的用户ID,并将其与连接标识进行映射。在收到消息时,获取目标用户的用户ID,并根据用户ID找到对应的连接标识,然后向该连接标识对应的用户推送消息。