> 백엔드 개발 > PHP 튜토리얼 > 我写的一个PHP即时聊室天方案

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

WBOY
풀어 주다: 2016-06-23 14:04:15
원래의
1096명이 탐색했습니다.

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

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 开源微博系统,参照那个吧,现在已经比较成熟了。

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿