Home > Article > Backend Development > 我写的一个PHP即时聊室天方案
并没有写具体的数据交互, 只是实现了核心功能的原理, 即时的连续的传输数据给客户端.
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 开源微博系统,参照那个吧,现在已经比较成熟了。