我想实现一个聊天室使用PHP / Javascript(Jquery)与群聊和私人聊天功能。
@H_403_2@问题是如何以自然的方式不断更新界面,以及如何在私人聊天中显示“X正在输入..”消息。
@H_403_2@显而易见的方式似乎是每X秒/毫秒javascript ping服务器,并获取一个新的邮件列表之间的最后一个ping和现在。然而,这可以使接口看起来有点不自然,如果突然聊天室充斥着5条消息。我宁愿每个消息显示,因为它是键入。
@H_403_2@有没有办法让javascript来维护与服务器的连续连接,服务器将任何新消息推送到此连接,并且javascript将它们添加到接口,以便它们同时显示,几乎只要服务器收到它们?
@H_403_2@我知道有一些轮询选项,需要你安装一些apache模块等,但我很糟糕的sysadmin,因此我更喜欢如果有一个很容易安装解决方案在共享的主机帐户,或者PHP / MysqL only解决方案。
解决方法
与PHP / AJAX / JSON聊天
@H_403_2@我使用这本书/教程来编写我的聊天应用程序:
@H_403_2@AJAX and PHP: Building Responsive Web Applications: Chapter 5: AJAX chat and JSON。
@H_403_2@它显示如何从头写一个完整的chatscript。
@H_403_2@基于彗星的聊天
@H_403_2@您也可以使用Comet与PHP。
@H_403_2@发件人:zeitoun:
@H_403_2@Comet使Web服务器可以向客户端发送数据,而不需要客户端请求它。因此,这种技术将产生比传统的AJAX更响应的应用程序。在经典的AJAX应用程序中,无法实时通知Web浏览器(客户端)服务器数据模型已更改。用户必须创建一个请求(例如通过点击一个链接)或者定期发送AJAX请求,以便从服务器获取新数据。
@H_403_2@我将向您展示使用PHP实现Comet的两种方法。例如:
@H_403_2@>基于隐藏的< iframe>使用服务器时间戳
>基于经典的AJAX非返回请求 @H_403_2@第一个在客户端上实时显示服务器日期,显示一个迷你聊天。 @H_403_2@方法1:iframe服务器时间戳 @H_403_2@你需要: @H_403_2@>后端PHP脚本来处理持久的http请求backend.PHP
>一个frondend HTML脚本加载Javascript代码index.html
> prototype JS library,但你也可以使用jQuery @H_403_2@后端脚本(backend.PHP)将执行无限循环,并且只要客户端连接,就会返回服务器时间。
>做一个无限循环,只要“data.txt”文件不变
> Gmail/Facebook Style jQuery Chat – 此jQuery聊天模块使您能够将Gmail / Facebook风格聊天无缝集成到您的现有网站。
> Writing a JavaScript/PHP Chat Server – 教程
> CometChat – CometChat在标准共享服务器上运行。只有PHP MysqL需要。
>基于经典的AJAX非返回请求 @H_403_2@第一个在客户端上实时显示服务器日期,显示一个迷你聊天。 @H_403_2@方法1:iframe服务器时间戳 @H_403_2@你需要: @H_403_2@>后端PHP脚本来处理持久的http请求backend.PHP
>一个frondend HTML脚本加载Javascript代码index.html
> prototype JS library,但你也可以使用jQuery @H_403_2@后端脚本(backend.PHP)将执行无限循环,并且只要客户端连接,就会返回服务器时间。
<?PHP header("Cache-Control: no-cache,must-revalidate"); header("Expires: Sun,5 Mar 2012 05:00:00 GMT"); flush(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Comet PHP backend</title> <Meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <script type="text/javascript"> // KHTML browser don't share javascripts between iframes var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML"); if (is_khtml) { var prototypejs = document.createElement('script'); prototypejs.setAttribute('type','text/javascript'); prototypejs.setAttribute('src','prototype.js'); var head = document.getElementsByTagName('head'); head[0].appendChild(prototypejs); } // load the comet object var comet = window.parent.comet; </script> <?PHP while(1) { echo '<script type="text/javascript">'; echo 'comet.printServerTime('.time().');'; echo '</script>'; flush(); // used to send the echoed data to the client sleep(1); // a little break to unload the server cpu } ?> </body> </html>@H_403_2@前端脚本(index.html)创建一个“彗星”javascript对象,将后端脚本连接到时间容器标记。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Comet demo</title> <Meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="prototype.js"></script> </head> <body> <div id="content">The server time will be shown here</div> <script type="text/javascript"> var comet = { connection : false,iframediv : false,initialize: function() { if (navigator.appVersion.indexOf("MSIE") != -1) { // For IE browsers comet.connection = new ActiveXObject("htmlfile"); comet.connection.open(); comet.connection.write("<html>"); comet.connection.write("<script>document.domain = '"+document.domain+"'"); comet.connection.write("</html>"); comet.connection.close(); comet.iframediv = comet.connection.createElement("div"); comet.connection.appendChild(comet.iframediv); comet.connection.parentWindow.comet = comet; comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='./backend.PHP'></iframe>"; } else if (navigator.appVersion.indexOf("KHTML") != -1) { // for KHTML browsers comet.connection = document.createElement('iframe'); comet.connection.setAttribute('id','comet_iframe'); comet.connection.setAttribute('src','./backend.PHP'); with (comet.connection.style) { position = "absolute"; left = top = "-100px"; height = width = "1px"; visibility = "hidden"; } document.body.appendChild(comet.connection); } else { // For other browser (Firefox...) comet.connection = document.createElement('iframe'); comet.connection.setAttribute('id','comet_iframe'); with (comet.connection.style) { left = top = "-100px"; height = width = "1px"; visibility = "hidden"; display = 'none'; } comet.iframediv = document.createElement('iframe'); comet.iframediv.setAttribute('src','./backend.PHP'); comet.connection.appendChild(comet.iframediv); document.body.appendChild(comet.connection); } },// this function will be called from backend.PHP printServerTime: function (time) { $('content').innerHTML = time; },onUnload: function() { if (comet.connection) { comet.connection = false; // release the iframe to prevent problems with IE when reloading the page } } } Event.observe(window,"load",comet.initialize); Event.observe(window,"unload",comet.onUnload); </script> </body> </html>@H_403_2@方法2:AJAX非返回请求 @H_403_2@您需要与方法1中相同的dataexchange(data.txt)文件, @H_403_2@现在,backend.PHP将做2件事: @H_403_2@>发送新消息时写入“data.txt”
>做一个无限循环,只要“data.txt”文件不变
@H_403_2@06002 @H_403_2@$_GET[‘timestamp’] : 0;@H_403_2@前端脚本(index.html)创建< div id =“content”>< / div>标签帽子将包含来自“data.txt”文件的聊天消息,最后它创建一个“彗星”javascript对象,它将调用后端脚本以便观看新的聊天消息。 @H_403_2@彗星对象将在每次接收到新消息时和每次发布新消息时发送AJAX请求。持久连接仅用于观看新消息。时间戳url参数用于标识最后请求的消息,以便服务器只有在“data.txt”时间戳比客户端时间戳更新时才会返回。
$currentmodif = filemtime($filename);
while ($currentmodif <= $lastmodif) // check if the data file
has been modified
{
usleep(10000); // sleep 10ms to unload the cpu
clearstatcache();
$currentmodif = filemtime($filename);
} @H_403_2@06003
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Comet demo</title> <Meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="prototype.js"></script> </head> <body> <div id="content"> </div> <p> <form action="" method="get" onsubmit="comet.doRequest($('word').value);$('word').value='';return false;"> <input type="text" name="word" id="word" value="" /> <input type="submit" name="submit" value="Send" /> </form> </p> <script type="text/javascript"> var Comet = Class.create(); Comet.prototype = { timestamp: 0,url: './backend.PHP',noerror: true,initialize: function() { },connect: function() { this.ajax = new Ajax.Request(this.url,{ method: 'get',parameters: { 'timestamp' : this.timestamp },onSuccess: function(transport) { // handle the server response var response = transport.responseText.evalJSON(); this.comet.timestamp = response['timestamp']; this.comet.handleResponse(response); this.comet.noerror = true; },onComplete: function(transport) { // send a new ajax request when this request is finished if (!this.comet.noerror) // if a connection problem occurs,try to reconnect each 5 seconds setTimeout(function(){ comet.connect() },5000); else this.comet.connect(); this.comet.noerror = false; } }); this.ajax.comet = this; },disconnect: function() { },handleResponse: function(response) { $('content').innerHTML += '<div>' + response['msg'] + '</div>'; },doRequest: function(request) { new Ajax.Request(this.url,parameters: { 'msg' : request }); } } var comet = new Comet(); comet.connect(); </script> </body> </html>@H_403_2@或者 @H_403_2@你也可以看看其他聊天应用程序,看看他们是如何做到的: @H_403_2@> http://hot-things.net/?q=blite – BlaB! Lite是一个基于AJAX的,最好的浏览器支持任何浏览器聊天系统,sqlite& Postgresql数据库。
> Gmail/Facebook Style jQuery Chat – 此jQuery聊天模块使您能够将Gmail / Facebook风格聊天无缝集成到您的现有网站。
> Writing a JavaScript/PHP Chat Server – 教程
> CometChat – CometChat在标准共享服务器上运行。只有PHP MysqL需要。