使用swoole实现实时消息推送给客户端

一. 测试服务端

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值