使用Comet和PHP进行实时数据更新?

4

我希望在我的社交网络网站上实现实时通知更新。我已经对comet进行了一些研究,我真的很着迷。

据我所知,这是在comet服务器上发生的基本流程。

Webpage: 
Sends an ajax request to server when the document is ready. 

Server:
Queries the database every x amount of seconds and returns a json string containing results if any are found.

Webpage:
Receives the result of the json string from the server and sends out another ajax request  to do the above process again.

通过了解comet的工作流程,我编写了一些PHP和Javascript代码。

Javascript代码使用jQuery库,并向服务器发送一个ajax请求,将当前时间以unix时间戳格式作为GET参数。

    $(document).ready(function(){
       var timestamp = Math.round(new Date().getTime() / 1000);

        function comet2(){
            $.ajax({
                type : 'GET',
                url  : 'comet.activities.php?timestamp=' + timestamp,
                async : true,
                cache : false,

                success : function(data) {
                    alert("current timestamp "+timestamp)

                    var json = JSON.parse(data);
                    if(json !== null){
                        alert(data);
                    }

                    timestamp  = json[0].timestamp;
                    setTimeout('comet2()', 1000);

                },
                error : function(XMLHttpRequest, textstatus, error) { 
                    setTimeout('comet2()', 15000);
                }       
            });
        }

        //call the comet function because the page has loaded.
        comet2();

    });

这段 PHP 代码将会通过使用时间戳参数(在此例中为查询中的 Unix 时间戳)来搜索数据库中的新行,以查询新活动。对于这个示例,我将结果数量限制为 1。

<?php 
    set_time_limit(0);
    include("models/config.php");
    global $mysqli,$db_table_prefix;

    $last = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
    $results = null;
    $flag=true;

    $stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp > ? ORDER BY timestamp DESC LIMIT 0,1");
    $stmt->bind_param("i", $last);
    $stmt->bind_result($id,$timestamp);

    while($flag){
        $stmt -> execute();    

        while ($row = $stmt->fetch()){
            $flag = false;
            $results[] = array(
                "id" => $id,       
                "timestamp" => $timestamp  
            );
        }

        $stmt -> close();  

        usleep(100000);
        clearstatcache();
    }

    echo json_encode($results);    

?> 

上述代码实际上并不能正常运作。问题在于,如果用户发布新评论,当comet脚本正在运行时,它将无法添加到数据库中。这意味着,comet脚本永远不会返回任何json结果,因为sql查询语句中的语句从未得到满足(没有添加具有更新时间戳的新活动)。我的用于发布新评论的ajax代码已经完全可用,所以我知道那不是问题所在。简而言之,“什么也没发生”,也就是没有任何警报或输出到浏览器控制台。
第3次编辑: 我非常困难地解释了“什么也没有发生”的含义,因此我上传了一张图片,展示了当从jquery调用comet脚本时,数据库插入失败的情况(请注意,在通过ajax发布评论时,文本框被禁用)。
有什么办法可以解决这个问题吗?我花了几个小时在互联网上搜索来尝试修复这个问题/找到类似的工作示例,但都没有成功。
如果我更改PHP代码中的查询为:
$stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp **<** ? ORDER BY timestamp DESC LIMIT 0,1");

改为:

 $stmt = $mysqli->prepare("SELECT id,timestamp FROM uc_user_activity WHERE timestamp > ? ORDER BY timestamp DESC LIMIT 0,1");

结果会立即在浏览器窗口中提醒,可以再次发布评论并调用脚本以显示新的帖子。这表明我的代码“在工作”,看起来查询是引起问题的原因...

enter image description here

有人能看出这里发生了什么吗?我已经编辑了这个问题7次了,任何指导都将是非常好的,因为我一无所获。

为了防止被关闭,我将我的问题总结如下:

有没有更好的实现comet服务器的方法?虽然我不算最有经验的人,但我真的很想学习如何做到这一点。StackOverflow似乎具有此功能并且完美地运行-他们是如何做到的?

我已经尽可能详细地写了我的帖子,我真的非常感谢你们这些了不起的人能够给予指导。一个关于为什么我的代码“无法工作”的建议或有关如何实现此功能的教程链接将是惊人的!提前致谢,对于这个庞然大物般的问题和所有编辑,我表示歉意!


1
我会进行编辑以解释这个问题。因为你评论得非常迅速,所以给你点赞! - Joel Murphy
3
"我做得对吗?" --- 用PHP编写的彗星服务器已经是一个糟糕的决定。 - zerkms
1
我做了一些修改,希望更加清晰易懂。你有什么建议吗?我对这个话题完全不熟悉,所以任何指导都将是巨大的帮助。谢谢 :) - Joel Murphy
1
你会推荐什么编程语言呢?它可以自己提供HTTP服务并支持线程。 - zerkms
1
我又进行了一次编辑:p 我很难解释发生了什么,因为我实际上不知道正在发生什么。基本上,当运行彗星代码时,我无法添加新评论(使用ajax),因为从未向数据库添加新帖子,因此查询从未触发返回任何结果。 - Joel Murphy
显示剩余6条评论
2个回答

0

因此,有关使用PHP的Comet的最佳可用教程在此处。 http://www.zeitoun.net/articles/comet_and_php/start

如果它有所帮助,请点赞:)

对于那些想要使用上面链接中的简单聊天解决方案与jQuery的人,这是解决方案。

<script type="text/javascript">
    var Comet = {};
    Comet.jquery = {
        timestamp: 0,
        url: './backend.php',
        noerror: true,
        initialize: function () {
        },
        connect: function ()
        {
            this.ajax = $.ajax({
                type: "get",
                url: this.url,
                data: {timestamp: this.timestamp},
                success: function (data) {
                    // handle the server response
                    var response = JSON.parse(data);
                    console.log(response);
                    //alert(response.timestamp);
                    Comet.jquery.timestamp = response.timestamp;
                    Comet.jquery.handleResponse(response);
                    Comet.jquery.noerror = true;
                },
                complete: function (data) {
                    // send a new ajax request when this request is finished
                    if (!Comet.jquery.noerror) {
                        // if a connection problem occurs, try to reconnect each 5 seconds
                        setTimeout(function () {
                            Comet.jquery.connect()
                        }, 5000);
                    }
                    else {
                        Comet.jquery.connect();
                    }
                    Comet.jquery.noerror = false;
                }
            });
        },
        disconnect: function ()
        {
        },
        handleResponse: function (response)
        {
            $('#content').append('<div>' + response.msg + '</div>');
        },
        doRequest: function (request)
        {
            $.ajax({
                type: "get",
                url: this.url,
                data: {'msg': request}
            });
        }
    }
</script>

0

我猜测你传递的时间戳值没有返回结果。你可以通过Javascript获取当前时间。查询会查询此时间戳之后的所有帖子。

你能否尝试打印查询并手动运行相同的查询,以确保它从数据库中检索到数据?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接