首页 文章

在PHP和Javascript中同步由服务器触发的多个客户端

提问于
浏览
0

我在具有LAMP配置的共享托管空间(Aruba)上运行服务器,具有两组独立的PHP页面,一组用于管理员,一组用于多个客户端(想象一下管理员提交问题的问答游戏) .

我想实现这种行为:

  • 管理员按下按钮并释放问题

  • 在十秒内(甚至是立即,但并非严格要求)的任何时间,所有客户必须在同一时间显示带有问题文本的页面 .

为实现这一目标,我想到了不同的解决方案:

  • Web sockets (不可行,因为我无法在我的网页上安装服务器组件)

  • Trigger file 由管理员生成;客户端将定期(~10秒)轮询( setInterval() )以查看是否存在此文件,并且根据文件的创建时间(或从文件名或文件内容中读取的等效时间戳),客户端将开始倒计时( setTimeout() )为必须触发新页面的剩余时间,以确保所有客户端最终同时触发(十分之一秒)

  • Trigger via database (与触发文件基本相同,但可能更慢) .

我在PHP和Javascript中尝试了第二个解决方案(在客户端管理触发器文件的读取),但是当连接的客户端不止时它们都会失败:

  • PHP 显然失败了,因为Apache不支持许多同步线程并且以某种方式卡住了

  • Javascript 偶尔会错过识别本地目录中存在的文件(连接多个客户端 XMLHttpRequest.status 错误地返回 404 ,即使触发器文件存在) - 我甚至为不同的客户端创建了单独的触发器文件,以确保没有并发冲突 .

有关为什么_416044偶尔会失败的任何提示,或有关更好地实现此行为的建议?

先感谢您 .

2 回答

  • 0

    编辑:我原来的答案中没有完全理解这个问题 . 这是我精确的答案:

    根据您目前的限制,我只看到了实现同步服务器响应的一种方法 . 首先,您需要实现HTML5 SSE(服务器端事件) . 当您的服务器准备好向客户端发送消息时,触发SSE发送到每个客户端 . 此事件不需要发送任何数据,因此不需要同时联系客户端 . 该事件告诉客户端对php ajaxHandler执行ajax调用 .

    在来自客户端的每次ajax调用期间,服务器将在您创建的某个表中检查数据库中“waitingClients”的值 . 如果值为0,则将值设置为1.如果该值大于0,则将waitingClients值增加1.在每次ajax调用增加数据库值之后,将在while循环中暂停各个ajax调用,直到'waitingClients '等于'totalClients'的值 . 我建议您在数据库中创建一些记录活动客户端数量的条目 . 这使您的'totalClients'值更具动态性 .

    你可能会遇到问题,ajax调用会在30秒后超时 . 由于您只返回数据库值,我怀疑您是否会遇到此问题,除非客户端的连接挂起 .

    这是一些示例代码(未经测试):

    HTML

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <script src="jquery-1.9.1.min.js"></script>
        <script src="ajaxTest.js"></script>
    </head>
    <body>
        <div id="server_message">Waiting for server response</div>
    </body>
    </html>
    

    阿贾克斯:

    $(function() {
       var message = $('#server_message');
        $.ajax({
            url: 'yourAjaxHandler.php',
            type: 'POST',
            data: {
                getAnswer: true
            },
            success: function(response) {
                console.log(response);
                message.text(response);
            }
        })
    });
    

    PHP Ajax处理程序

    <?php
    
    $host = 'db host address';
    $dbname = 'your database name';
    $username = 'your username';
    $password = 'your password';
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    
    // Define expected number of total clients. I would recommend having clients log an entry into the database upon initial login/connection.
    // This would make tallying the number of clients more dynamic. Otherwise you will always need 4 clients connected
    $totalClients = 4;
    
    if (isset($_REQUEST['getAnswer'])) {
    
        $qry = 'SELECT waitingClients from some_table';
        $waitingClients = $conn->query($qry);
    
        if ($waitingClients === 0) {
            // Create waitingClients in database if it doesn't exist. Otherwise, increment value to 1
            $qry = "UPDATE some_table set waitingClients = 1";
            $conn->exec($qry);
        } else {
            // Increment waitingClients
            $qry = "UPDATE some_table set waitingClients = waitingClients + 1";
            $conn->exec($qry);
        }
    
        while ($waitingClients <= $totalClients) {
            // The while loop will keep the ajax call active for all clients
            // Keep querying database until waitingClients value in DB matches the number of totalClients
            $qry = 'SELECT waitingClients from some_table';
            $waitingClients = $conn->query($qry);
        }
    
        // Set the value of waitingClients back to 0
        $qry = "UPDATE some_table SET waitingClients = 0";
        $conn->exec($qry);
    
        // Return your server message to the clients
        echo json_encode("Your server message"); // You could also store your server message in the database
    }
    
  • 0

    你考虑过长时间的民意调查吗?有关如何使用PHP执行此操作的示例,请参阅https://github.com/panique/php-long-polling . 由于必须保持活动的apache和php进程的数量,这将无法很好地扩展,但对于少数客户端来说会很好 . 如果你需要它可以扩展,那么我会考虑将服务器技术转换为像hack(如PHP;参见http://hacklang.org/)或节点这样的东西 .

相关问题