一. 测试服务端
//测试服务端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找到对应的连接标识,然后向该连接标识对应的用户推送消息。