【问题标题】:best way to update chat room quickly, and reliably?快速、可靠地更新聊天室的最佳方法?
【发布时间】:2015-06-04 16:17:00
【问题描述】:

我正在开发一个基本的聊天服务,它基本上是一个学校项目,将在学生中使用。我一直很成功,但是我遇到了一个问题。更新聊天室。在我的许多测试中,它往往会使用长达 10 秒的时间来接收消息并被发送它的用户识别。

运行 php 将消息推送到聊天文件和 jquery 加载该文件。聊天每 3 秒更新一次。在我的测试中,聊天文件会立即更新,但实际聊天不会更新得那么快,平均大约 10 秒。

我相信这一定是 jquery 中的一些限制。我应该离开 jquery 并找到更好的解决方案,还是我的代码有问题?任何帮助是极大的赞赏。提前致谢!

里面也有一些php,只是加载用户名和房间名

jQuery 代码:

    var roomname = "<?php echo $_GET["room"]; ?>";
    var prevdata = "";
    update();
    setInterval(function(){update()},3000)
    $("#send").click(function(){
        sendMessage();
    });

    $('#message').keyup(function(e){
        if(e.keyCode == 13)
        {
            sendMessage();
        }
    });

    function update()
    {
        $.get("/rooms/room/"+roomname+".html",function(data){
            $("#chatbox").html(data);
            if(prevdata != data && data.indexOf("<?php echo $_SESSION["username"] ?>") != 31)
            {
            playMessageSound();
            }
            prevdata = data;
        });
    }

    function sendMessage()
    {
        var message = $("#message").val();
        $("#message").val("");
        $.get("sendmessage.php?room="+roomname+"&message="+message)
    }

    function playMessageSound()
    {
        var audio = new Audio("/sound/msg.mp3");
        audio.play();
    }

我的解决方案: 我采用了 jwatts 的解决方案并对其进行了一些定制,以使其代码行数更少。我现在只是将聊天与文件进行比较,然后返回差异,将它们附加到聊天中,使其尽可能快地更新!

感谢大家的帮助!

【问题讨论】:

  • 从我读到你的聊天延迟可能是服务器速度。当您以这么多的时间间隔进行更新时,将对内存使用造成影响。你考虑过套接字吗?
  • @MarkHill 不,我从未考虑过套接字。你有我可以挖掘的资源吗?我是一个狂热的程序员,我对这个场景很陌生。任何帮助都会很可爱。谢谢!
  • 给我一点,我会给你一个答案

标签: php jquery html chat


【解决方案1】:

我知道这个问题已经得到解答,但我想提出另一个可能的解决方案。就这些事情而言,这是一个简单的,有一些注意事项和警告,但对于一个课堂项目来说就足够了。我提出的示例不是我自己创建的,并且代码未经测试。您可能会花费相当多的时间来实施更改并让它们发挥作用。

但它探讨了一些基本的数据格式,例如 PHP 和 JavaScript 中的 XML 和 JSON 功能。它跟踪最近的数据抓取,只获取新的聊天信息。这样,一旦数据返回浏览器,它只会加载新内容而不是整个内容。

在您上面的代码中,看起来您每次都在编写整个聊天。我确信存在一些浏览器缓存问题。与其每次都请求整个 html 页面,不如请求一个 PHP 来返回 JSON 数据(PHP 具有内置的 JSON 函数),该数据仅包含最后的条目,然后将它们附加到文档中。

有很多关于 JSON 的信息。如果您还没有了解它,它是一种 JavaScript 原生的数据表达方式。它可以将 JSON 格式的文本本地转换为数组、对象和属性。而且它不像 XML 那样冗长。

在您的代码中,创建一个名为

的时间戳
var lastDataReceived = "";

这将保留上次从服务器接收到新聊天数据的时间戳。在$.get() success 函数中,将 URL 更改为 PHP 页面并将其设置为获取 JSON 数据。另外,传入所需的信息,例如您需要数据的房间的名称,以及上次收到聊天数据的时间:

function update()
{
    $.get({
        url: "/rooms/room/getchatdata.php",
        data: { "room": roomname, "lastDataReceived": lastDataReceived }, 
        success: function(data){
            //..............
        },
        dataType: "json"
    });
}

这将创建一个请求

"/rooms/room/chatdata.php?room="+roomname+"&lastDataReceived="+lastDataReceived 

在服务器端,可以这样获取查询字符串参数

$roomname = $_GET["room"];
$lastDataReceived = date_create_from_format('d/M/Y H:i:s', $_GET["lastDataReceived"]);

看起来您正在将聊天信息写入 HTML 文件。在此示例中,使用 XML 数据很可能更可取。那里有很多很多 PHP XML 教程。这是 W3Schools.com 上关于 SimpleXML 函数的一个。 (http://www.w3schools.com/php/php_ref_simplexml.asp)

这样你就可以从文件中加载:

$xml = simplexml_load_file($roomname.".xml");

如果是新房间,也可以创建一个新的 XML 文件,例如:

<?php
    $chats = <<<XML
        <chats>
        </chats>
        XML;

    $xml = new SimpleXMLElement($chats);
    $xml->saveXML($roomname.".xml");
?>

要确定是读还是写,可以通过检查该房间的文件是否存在来检查该房间是否存在:

$xml = NULL;
if (file_exists($roomname.".xml")) {
    //Set to exsiting
    $xml = simplexml_load_file($roomname.".xml");
} else {
    //Create new file   
    $chats = <<<XML
        <chats>
        </chats>
        XML;
    $xml = new SimpleXMLElement($chats);
    $xml->saveXML($roomname.".xml");
}

无论哪种方式,您都会得到一个可以使用的$xml 变量。

现在,假设您已将请求发回服务器以查看是否有任何新的聊天数据。您正在使用之前创建的变量$roomname$lastDataReceived。您已经从文件中加载了$xml 对象。现在您需要找到任何新添加的内容。

$chats = $xml->chats->children();
$newchats = array();

foreach($chats as $c) {
    if ($c['date'] > $lastDataReceived) {
        array_push($newchats, $c);
    }
}

现在您有了一个新聊天项目的数组,将 JSON 数据写回浏览器:

$json = json_encode($newchats);
header('Content-Type: application/json');
echo $json;

现在回到你的 JavaScript。在上面的 PHP 示例中,$newchats 被初始化为一个新数组。当json_encode() 被调用时,如果没有新的聊天,echo 将返回一个空数组。您可以在 JS 中对此进行测试。

在这种情况下,您只需要添加新的项目。因此您需要将新的 HTML 添加到文档中。使用 jQuery,这非常容易。假设聊天都在&lt;div&gt; 标签中:

<div id="chats">
    <!--all chats here-->
</div>

你有一个模板div,你希望所有聊天看起来像

<div class="chat_template" style="display:none;">
    <div class="person_name"></div>
    <div class="chat_text"></div>
    <div class="chat_time"></div>
</div>

您可以克隆它,将数据加载到其中,并将其附加到文档中。

function update()
{
    $.get({
        url: "/rooms/room/chatdata.php",
        data: { "room": roomname, "lastDataReceived": lastDataReceived }, 
        success: function(data){
            if (data.length > 0) {
                for (var i = 0; i < data.length; i++) {[
                    var c = data[i];
                    //I do not know what the exact structure of the data will be.
                    // You may need to output the data to the console to see it's structure.
                    // But I am assuming you will have access to the date value, the person's name
                    // and the text.

                    //Clone the template and add the values
                    var div = $("div.chat_template").clone(true);
                    div.find("div.person_name").html(name);
                    div.find("div.chat_text").html(text);
                    div.find("div.chat_time").html(date_val);
                    div.show();

                    //Add the new div to the document
                    $("div#chats").append(div);

                    //Set the last received time for the next query
                    lastDataReceived = date_val;
                }

                playMessageSound();
            }
        },
        dataType: "json"
    });
}

当向服务器发送新的聊天信息时,您可以在 jQuery $.post() 函数中使用相同的 data: { "chattext": text....} 类型结构。您将需要在服务器上使用不同的 PHP 文件,例如 addchatdata.php。我已经接触过一种算法,它可以根据聊天室文件是否存在来获取或创建它。

所以如果你想让子 XML 元素看起来像这样

<chat date="04/Jun/2015 13:18:23" name="George">
    Here is some of George's text.
</chat>

一旦你得到$xml 对象,你可以像这样向它添加新的XML:

$chat = $xml->addChild("chat", "Here is some of George's text.");
$chat->addAttribute("date", date('d/M/Y H:i:s'));
$chat->addAttribute("name", "George"); //<--Or use a variable name for the name

//Then save the changes back out to the file:
$xml->saveXML($roomname.".xml");

一般来说,这是在做您已经在做的事情:存储来自新聊天的数据,然后将该数据加载到连接到聊天的其他客户端。但是,这里只是检索新信息,在浏览器上加载速度会更快。

【讨论】:

  • 这是一个非常简单快捷的解决方案。我想我宁愿研究这个而不是另一个!非常感谢!
  • 我已经考虑了您的解决方案,并根据您的想法制作了自己的系统。我现在检查新消息,通过比较聊天消息中的字符和文件中的字符,减去那些使用 substr() 并返回结果!谢谢大佬!
【解决方案2】:

据我所知,您大致了解了脚本的工作原理,以及您想要做什么的总体概念。哪个好。

至于使您的应用程序更快。以目前的建造方式,在那里可以做的事情并不多。您可以做的最好的事情是查看您拥有的任何循环的速度,并检查它们是否过于深入,因为这会超频进程并降低从服务器检索数据的速度。

JSF 方法

我一直在研究 JSF(JavaServer Faces),它是一个用于基于服务器的应用程序的 J2EE 框架。它实现了 CSS、HTML 和其他语言的各种组件,据我所知,它用途广泛。根据您可以使用的语言类型,如果您至少具备上述语言和 Java 的基本知识,那么我建议您研究一下。

http://www.tutorialspoint.com/jsf/index.htm

如果您想要更快的概览,我还发现维基百科页面也很有帮助。

http://en.wikipedia.org/wiki/JavaServer_Faces

socket.io 和 node.js

这也是我发现的更有趣的东西,我不知道为什么我在回答这个问题时没有早点想到它。这使用了 html5 中 websockets 的新特性来创建响应良好的页面。使用起来更容易、更清洁,而且它与您正在尝试做的事情相得益彰。

这是我一直在使用的所有东西,如果您对此有任何疑问,请随时在此处发表评论,我会尽力为您提供更多信息

http://socket.io/

https://nodejs.org/

https://www.youtube.com/watch?v=pNKNYLv2BpQ

这是一个非常好的工具,我每天都推荐它而不是 JSF。

【讨论】:

  • 谢谢您,先生。我会慢慢来,看看我能用它做什么,一定会喜欢这个!
  • @AlexanderHansen 不要忘记接受答案,如果您认为这相关,请点赞
  • 我不得不说,这看起来真的很难。我会尽力而为!
  • 是的,这不是野餐,我只是自己参与其中,但它会非常棒!这也是一项非常好的综合技能。
  • @AlexanderHansen 检查我刚刚添加的更新,你可能更喜欢这个
猜你喜欢
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 2014-05-14
  • 2014-08-20
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多