快速、可靠地更新聊天室的最佳方式?
best way to update chat room quickly, and reliably?
我正在开发一个基本的聊天服务,它基本上是一个学校项目,将在学生中使用。我已经很成功了,但是我遇到了一个问题。更新聊天室。在我的许多测试中,它往往需要最多 10 秒的时间来接收消息并被发送消息的用户识别。
将消息推送到聊天文件和 jquery 加载该文件都是 运行 php。聊天每 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 的解决方案并对其进行了一些定制,以减少代码行数。我现在只是比较聊天和文件,return 差异,将这些附加到聊天中,使更新尽可能快!
感谢大家的帮助!
据我所知,您对脚本的工作原理有一个大致的了解,并且对您要执行的操作有一个总体概念。哪个好。
就让您的应用程序更快而言。按照目前的构建方式,在那里可以做的事情并不多。您能做的最好的事情就是查看您拥有的任何循环的速度,并检查它们是否太深,因为这可能会使进程超频并降低从服务器检索数据的速度。
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 的新特性来获得漂亮的响应页面。使用起来更容易、更简洁,而且它与您正在尝试做的事情相得益彰。
这是我一直在使用的所有东西,如果您对此有任何疑问,请不要犹豫,在这里发表评论,我会尽力为您提供更多信息
https://www.youtube.com/watch?v=pNKNYLv2BpQ
这是一个非常好的工具,我每天都推荐它而不是 JSF。
我知道这个问题已经得到解答,但我想提出另一种可能的解决方案。随着这些事情的发展,这是一个简单的问题,但有一些问题和注意事项,但对于 class 项目来说就足够了。我提出的示例不是我自己创建的,并且代码未经测试。并且您可能需要花费相当多的时间来实施更改并使它们生效。
但它探索了一些基本的数据格式,例如 PHP 和 JavaScript 中的 XML 和 JSON 功能。它跟踪最近的数据抓取并且只获取新的聊天信息。这样,一旦数据返回到浏览器,它只会加载新内容而不是整个内容。
在你上面的代码中,看起来你每次都在写整个聊天。我确定存在一些浏览器缓存问题。与其每次都请求整个 html 页面,不如请求一个 PHP return 的 JSON 数据(PHP 内置 JSON 函数)只包含最后的条目,然后将它们附加到文档中。
JSON 上有很多可用的信息。如果您还没有了解它,它是 JavaScript 原生的一种数据表达方式。它可以原生地将 JSON 格式的文本转换为数组、对象和属性。而且它不像 XML.
那样冗长
在您的代码中,创建一个名为
的时间戳
var lastDataReceived = "";
这将保留上次从服务器接收到新聊天数据的时间戳。在$.get()
成功函数中,将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
在服务端,可以这样获取querystring参数
$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
将 return 一个空数组。您可以在 JS 中对此进行测试。
在这种情况下,您只会添加进来的新项目。因此您需要向文档添加新的 HTML。使用 jQuery 这非常容易。假设聊天都在 <div>
标签中:
<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");
在一般意义上,这是在做您已经在做的事情:存储来自新聊天的数据,然后将该数据加载到连接到聊天的其他客户端。但是,这里只是检索新信息,在浏览器上加载速度会更快。
我正在开发一个基本的聊天服务,它基本上是一个学校项目,将在学生中使用。我已经很成功了,但是我遇到了一个问题。更新聊天室。在我的许多测试中,它往往需要最多 10 秒的时间来接收消息并被发送消息的用户识别。
将消息推送到聊天文件和 jquery 加载该文件都是 运行 php。聊天每 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 的解决方案并对其进行了一些定制,以减少代码行数。我现在只是比较聊天和文件,return 差异,将这些附加到聊天中,使更新尽可能快!
感谢大家的帮助!
据我所知,您对脚本的工作原理有一个大致的了解,并且对您要执行的操作有一个总体概念。哪个好。
就让您的应用程序更快而言。按照目前的构建方式,在那里可以做的事情并不多。您能做的最好的事情就是查看您拥有的任何循环的速度,并检查它们是否太深,因为这可能会使进程超频并降低从服务器检索数据的速度。
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 的新特性来获得漂亮的响应页面。使用起来更容易、更简洁,而且它与您正在尝试做的事情相得益彰。
这是我一直在使用的所有东西,如果您对此有任何疑问,请不要犹豫,在这里发表评论,我会尽力为您提供更多信息
https://www.youtube.com/watch?v=pNKNYLv2BpQ
这是一个非常好的工具,我每天都推荐它而不是 JSF。
我知道这个问题已经得到解答,但我想提出另一种可能的解决方案。随着这些事情的发展,这是一个简单的问题,但有一些问题和注意事项,但对于 class 项目来说就足够了。我提出的示例不是我自己创建的,并且代码未经测试。并且您可能需要花费相当多的时间来实施更改并使它们生效。
但它探索了一些基本的数据格式,例如 PHP 和 JavaScript 中的 XML 和 JSON 功能。它跟踪最近的数据抓取并且只获取新的聊天信息。这样,一旦数据返回到浏览器,它只会加载新内容而不是整个内容。
在你上面的代码中,看起来你每次都在写整个聊天。我确定存在一些浏览器缓存问题。与其每次都请求整个 html 页面,不如请求一个 PHP return 的 JSON 数据(PHP 内置 JSON 函数)只包含最后的条目,然后将它们附加到文档中。
JSON 上有很多可用的信息。如果您还没有了解它,它是 JavaScript 原生的一种数据表达方式。它可以原生地将 JSON 格式的文本转换为数组、对象和属性。而且它不像 XML.
那样冗长在您的代码中,创建一个名为
的时间戳var lastDataReceived = "";
这将保留上次从服务器接收到新聊天数据的时间戳。在$.get()
成功函数中,将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
在服务端,可以这样获取querystring参数
$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
将 return 一个空数组。您可以在 JS 中对此进行测试。
在这种情况下,您只会添加进来的新项目。因此您需要向文档添加新的 HTML。使用 jQuery 这非常容易。假设聊天都在 <div>
标签中:
<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");
在一般意义上,这是在做您已经在做的事情:存储来自新聊天的数据,然后将该数据加载到连接到聊天的其他客户端。但是,这里只是检索新信息,在浏览器上加载速度会更快。