在我目前正在从事的项目中,我们需要开发一个Web聊天应用程序,而不是一个非常复杂的聊天,仅是一种将两个人联系起来谈论一个非常具体的话题的方式,我们不需要任何东西对两个用户之一进行身份验证,我们不必支持表情符号,头像或类似的东西。
一些项目成员建议我们可以通过BOSH使用XMPP,我说这就像试图用船网抓鱼,并提出了一种更简单的方法,例如简单的Ajax / MySQL网络聊天,但我们担心有关由于同时打开多个聊天室的持续轮询而导致服务器性能下降的原因。
以前有人做过这样的事情吗?你会推荐什么?
您可能还想研究彗星。
它被GTalk,Meebo和许多其他聊天应用程序使用。几年前,当我尝试使用它时,并没有太多的库或有关服务器体系结构的细节来实现它,但是看起来现在还有更多的东西。
有关更多技术信息,请参见cometd项目。
What would you recommend?
通过BOSH的XMPP
在其他人拥有的情况下,无需发明自己的消息格式和传输协议。如果尝试使用,它将慢慢变得与BOSH一样复杂,但是没有第三方库支持或标准化的好处。
如果您不喜欢HTTP轮询的想法,则可以在聊天页面上创建一个Flash电影,该电影与服务器上的某些守护进程保持稳定的连接,然后,该Flash电影将在服务器上调用JavaScript函数。客户端以在出现新消息时更新聊天。 (除非您需要一个用于聊天的Flash界面。)
有一个非常好的服务器,用于处理从服务器到浏览器的消息推送(称为Comet)-绕行。就像memcached一样,它很容易与其他技术(Django,Rails,PHP等)集成。
如果您要处理严重的负载,则应该进行检查。否则,简单的Ajax轮询是最好的方法。
You might also want to look into Comet.
I thought everyone used cometd for this sort of thing.
BOSH是用于通过HTTP传输XMPP的标准。它涉及Comet将数据推送到客户端。
诀窍是要认识到您的应用唯一需要在服务器上调用CGI的时间是某人说些什么。对于常规轮询,请轮询一个静态页面,当有新聊天记录时,您的CGI脚本会更新该页面。使用HEAD请求,将时间戳与上次看到的时间戳进行比较,并仅在更改时执行完整的GET。我有一个以这种方式实现的简单的天真的聊天应用程序,对于我们拥有的数十个同时用户,负载和带宽的使用可以忽略不计。
几个月前,我做了同样的事情,并且在尝试这些概念时感到很开心。我实际上使用了永久帧技术而不是轮询。
下面的代码是我的" comet" js文件,其中包含获得"聚会聊天"设置所需的一般概念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| function Comet(key) {
var random = key;
var title = 'Comet';
var connection = false;
var iframediv = false;
var browserIsIE = /*@cc_on!@*/false;
var blurStatus = false;
var tmpframe = document.createElement('iframe');
var nl = '\
\
';
this.initialize = function() {
if (browserIsIE) {
connection = new ActiveXObject("htmlfile");
connection.open();
connection.write("<html>");
connection.write("document.domain = '"+document.domain+"'");
connection.write("</html>");
connection.close();
iframediv = connection.createElement("div");
connection.appendChild(iframediv);
connection.parentWindow.comet = comet;
iframediv.innerHTML ="<iframe id='comet_iframe' src='./comet.aspx?key="+random+"'></iframex>";
} else {
connection = document.createElement('iframe');
connection.setAttribute('id', 'comet_iframe');
iframediv = document.createElement('iframe');
iframediv.setAttribute('src', './comet.aspx?key='+random);
connection.appendChild(iframediv);
document.body.appendChild(connection);
}
}
// this function is called from the server to keep the connection alive
this.keepAlive = function () {
if (!browserIsIE) {
mozillaHack();
}
}
// this function is called from the server to update the client
this.updateClient = function (value) {
var outputDiv = document.getElementById('output');
outputDiv.value = value + nl + outputDiv.value;
if (blurStatus == true) {
document.title = value;
}
if (!browserIsIE) {
mozillaHack();
}
}
this.onUnload = function() {
if (connection) {
// this will release the iframe to prevent problems with IE when reloading the page
connection = false;
}
}
this.toggleBlurStatus = function(bool) {
blurStatus = bool;
}
this.resetTitle = function() {
document.title = title;
}
function mozillaHack() {
// this hack will fix the hour glass and loading status for Mozilla browsers
document.body.appendChild(tmpframe);
document.body.removeChild(tmpframe);
}
} |
我刚刚发现这篇文章,它很旧,但是民意测验的概念给很多人带来了麻烦。因此,我将在此处放置一个实现示例。但是在给您之前,我应该给您一些建议,这让我在一段时间前发疯了:
轮询时,应注意会话行为(竞赛条件)。简而言之:如果您打开一个会话,会话文件将被锁定,直到关闭该会话为止,以避免2个theads向其中写入不同的数据。因此,如果您需要会话来检查用户是否已登录,请始终在轮询之前关闭该会话。
我的演示为您提供了PHP中轮询实现的示例。我不会使用数据库,而是使用文件。当您单击轮询按钮时,您将进入循环,直到文件被修改,您将保持轮询状态。当您填写表格并单击下达时,您键入的内容将被保存到文件中。文件的修改时间将更改,因此轮询将停止。
提示:使用Firebug之类的工具查看发生的情况。
现在说的语言比我的英语更好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| <?php
// For this demo
if (file_exists('poll.txt') == false) {
file_put_contents('poll.txt', '');
}
if (isset($_GET['poll'])) {
// Don't forget to change the default time limit
set_time_limit(120);
date_default_timezone_set('Europe/Paris');
$time = time();
// We loop until you click on the"release" button...
$poll = true;
$number_of_tries = 1;
while ($poll)
{
// Here we simulate a request (last mtime of file could be a creation/update_date field on a base)
clearstatcache();
$mtime = filemtime('poll.txt');
if ($mtime > $time) {
$result = htmlentities(file_get_contents('poll.txt'));
$poll = false;
}
// Of course, else your polling will kill your resources!
$number_of_tries++;
sleep(1);
}
// Outputs result
echo"Number of tries : {$number_of_tries}<br/>{$result}";
die();
}
// Here we catch the release form
if (isset($_GET['release']))
{
$data = '';
if (isset($_GET['data'])) {
$data = $_GET['data'];
}
file_put_contents('poll.txt', $data);
die();
}
?>
<!-- click this button to begin long-polling -->
<input id="poll" type="button" value="Click me to start polling" />
<br/><br/>
Give me some text here :
<br/>
<input id="data" type="text" />
<br/>
<!-- click this button to release long-polling -->
<input id="release" type="button" value="Click me to release polling" disabled="disabled" />
<br/><br/>
Result after releasing polling :
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
<script type="text/javascript">
// Script to launch polling
$('#poll').click(function() {
$('#poll').attr('disabled', 'disabled');
$('#release').removeAttr('disabled');
$.ajax({
url: 'poll.php',
data: {
poll: 'yes' // sets our $_GET['poll']
},
success: function(data) {
$('#result').html(data);
$('#poll').removeAttr('disabled');
$('#release').attr('disabled', 'disabled');
}
});
});
// Script to release polling
$('#release').click(function() {
$.ajax({
url: 'poll.php',
data: {
release: 'yes', // sets our $_GET['release']
data: $('#data').val() // sets our $_GET['data']
}
});
}); |
你可以在这里尝试
结帐Speeqe。它是基于Web的聊天室的开源解决方案,在后台使用BOSH和XMPP。
我认为轮询是最简单的方法,因此建议先这样做。如果负载成为问题,那就开始研究更复杂的技术。
关于优缺点的很好的讨论在这里-
http://www.infoq.com/news/2007/07/pushvspull
http://ajaxian.com/archives/a-report-on-push-versus-pull
我同意约翰的观点。但是还有另一个问题没有得到回答。
我已经做到了,但是它没有使用数据库,而是使用了平面文件,它最终使服务器瘫痪了,但是直到我们有约450个活跃用户时才这样做,如果我们对数据库进行操作,它可能会失败了。更好。这是通过Godaddy的基本托管帐户完成的。
编辑:当我接到电话时,BTW Godaddy听起来不那么开心。
我以为每个人都用彗星做这种事情。