Heim >Backend-Entwicklung >PHP-Tutorial >我写的一个PHP即时聊室天方案

我写的一个PHP即时聊室天方案

WBOY
WBOYOriginal
2016-06-23 14:04:151107Durchsuche

并没有写具体的数据交互, 只是实现了核心功能的原理, 即时的连续的传输数据给客户端.

ajax = function(method, url, data) {    var objxml = jsuse.createXMLHttpRequest(); //自己写这个函数, 我使用了一个库.    if (url.indexOf("http://") != 0) {        url = jsuse.BASE_URL + url;    }    objxml.open(method, url, true); //异步调用    //objxml.setRequestHeader("Content-type", "application/x-octet-stream");    var pos = 0;    objxml.onreadystatechange = function() {        if (objxml.readyState == 4) {            if (objxml.status == "200") {                document.write("200 OK");            } else {                //document.write(objxml.status);            }        } else if(objxml.readyState == 3) {            var str = objxml.responseText;            document.write(str.substr(pos));            pos = str.length;        } else {            document.write(objxml.readyState+"<br />");        }    }    try {        objxml.send(data);    } catch (e) {        return false;    }    return true;}jsuse(function(){    ajax("post","test.php",""); //这一句会在onLoad里加载, 可以写在body的onLoad里.});

set_time_limit(0); //设置页面永不超时for($i=0;$i<3000;$i++){ //先把浏览器缓存冲掉, 不同浏览器这个值不同.    echo " ";}ob_implicit_flush(true); //设置PHP实时输出$n = 0;while(true) {  echo "$n yeah :-))))<br />";  @ob_flush();//刷新缓冲.  sleep(1);  $n++;}

测试客户端可以持续的接收到服务端的数据. 

我想问的是这种方案在客户端较多的时候资源占用怎样? 实际上是一个持续连接, 资源占用比播放视频低得多. 另外, 聊天的时候, 用户提交的文本应该是用一个数据库存储和协调的, 这就意味这这个数据库是持续打开的, 用户多了以后会不会有问题?


回复讨论(解决方案)

另外还有2个问题:

1. 服务端是每隔一秒, 刷新一下数据库, 看有没有新数据. 有没有优化的方案?

2. 不同的聊天室, 数据是没有关联的, 但是如果把不同的聊天室数据保存在同一个表中(毕竟, 这些数据如果不需要保存的话, 实际上一个聊天室占用的存储空间是很小的, 格式又相同, 没有必要每个聊天室建一个表), 通过一个标识来区分, 那么不同的聊天室读写数据库会不会互相加锁, 降低效率.

先说一下代码问题:
1、你在函数中用了 document.write ,那么你的程序能正常运行吗?
2、把浏览器缓存冲掉,这一动作需在每次输出时做。你只在循环外做一次,能保证气候的数据能实时显示吗?

回到方案上:
每一次执行 ajax 都将产生一个新的 http 会话,也就是服务器每次都会执行一个php程序的副本。那么,你让被执行的php程序处于死循环中的意义何在?

让客户端ajax定时去调接口就行了,没必要做死循环

先说一下代码问题:
1、你在函数中用了 document.write ,那么你的程序能正常运行吗?
2、把浏览器缓存冲掉,这一动作需在每次输出时做。你只在循环外做一次,能保证气候的数据能实时显示吗?

回到方案上:
每一次执行 ajax 都将产生一个新的 http 会话,也就是服务器每次都会执行一个php程序的副本。那么,你让被执行的php程序处于死循环中的意义……

版主啊, 你真的是版主吗?

1. 这是测试代码, document.write的确能输出啊, 哪里有问题? 明确一下. 实际上当中, 不太可能用write函数.
2. PHP代码那几行, 处理的就是这些问题, 本来PHP和浏览器都会有缓存, 这是对的, 为了提高效率一次传输数据, 效率高, 但是我们的需求就是不要这种机制, echo之后, 希望数据即时的在浏览器显示出来. ob_implicit_flush(true)和ob_flush就是起这个作用的. 但是即使如此, 浏览器自己还有缓冲, 如果数据量很小, 它会等待关闭连接后, 一次显示出来, 当然了在常规http应用中, 这种优化是非必要的, 但是现在, 也是要避免它, 所以用来3000个空格, 目的是字符足够多, 能够触发显示. 实测, 只需要第一次, 后面的数据就不需要冲了, 一个字符也会即时显示.
3. 虽然是死循环, 用户刷新之后, 页面仍然会停止, 当然, 即时通讯, 肯定要保持一个长连接. 任何语言的服务器也不可避免.

这些代码在本地服务器运行良好, 可是在sae平台, 它把这几个关键函数都禁掉了.

像这种定时请求服务器资源的PHP应用对服务器的压力会很大!建议类似聊天室的使用Node.js来做!

回应3:
对ajax来说,只有当服务器执行完毕,ajax的回调函数才会被调用。因此你所说的长连接实际上是起不作用的,也许你根本没有测试过你写的代码。

回应3:
对ajax来说,只有当服务器执行完毕,ajax的回调函数才会被调用。因此你所说的长连接实际上是起不作用的,也许你根本没有测试过你写的代码。

无语. 我没测试, 难道你测试了? 

说句惹你们不高兴的话, 也是有勋章的人了, 技术上认真点.

引用 8 楼 dream1206 的回复:回应3:
对ajax来说,只有当服务器执行完毕,ajax的回调函数才会被调用。因此你所说的长连接实际上是起不作用的,也许你根本没有测试过你写的代码。

无语. 我没测试, 难道你测试了? 

说句惹你们不高兴的话, 也是有勋章的人了, 技术上认真点. 抱歉是我的无知,之前一直以为只有当响应内容全部加载完毕,responseText才会被赋值。

StatusNet 开源微博系统,参照那个吧,现在已经比较成熟了。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn