采用PHP实现”服务器推”技术的聊天室
本文将通过结合Ticks(可以参看我的另外一篇文章:关于PHP你可能不知道的-PHP的事件驱动化设计),来实现一个服务器推的PHP聊天室简单构想。
PHPer,尤其是用过set_cookie, header的,一定见过这样的提示信息:”Warning: Cannot modify header information – headers already sent by…..”, 这是因为通过HTTP协议通信,数据包会包含俩个部分,一个是Header,一个是data。一般来说,都是先Header部分,在Heaer部分指明了 Data部分的长度,然后使用\r\n\r\n来表示header部分结束,接下来是Data部分。
当我们有任何输出的时候,Header部分就发送了,这个时候,你再想header函数来改变一些Header部分的域信息,就会得到上面的提示信息。
一个简单的办法就是使用output_buffering。让它来缓存服务器的输出,不要太早将Header部分发给客户端。
那么,如果不使用output_buffering,是不是就可以实现,每当服务器有输出,就立即发送给客户端呢?
做个如下试验:
//设置php.ini中output_buffering=0 或者使用ob_end_flush()关闭缓存
- set_time_limit(0);for($i=0;$i<10;$i++){echo "Now Index is :". $i;sleep(1);}
结果我们发现,还是要等到脚本全部执行完以后,才能一次看到所有的结果。。
为什么呢?
这是因为我们只是解决了缓存问题,但是还有一个缓冲问题,PHP会缓冲程序的输出。所以,这个时候,我们还需要调用,flush(), 来强制使得PHP将所有的程序输出发送给客户端。
- set_time_limit(0);//设置php.ini中output_buffering=0ob_end_flush();//关闭缓存set_time_limit(0);for($i=0;$i<10;$i++){echo "Now Index is :". $i;flush();sleep(1);}
现在是不是看到了,不断有服务器的数据显示出来(如果看不到, 可以在输出前填充相当数量的占位字符)?
有几个概念之间的关系,我这里补充以下:
在代码中使用ob_start(), 就相当于在php.ini中使用output_buffering=on一样,使用服务器缓存。
在代码中使用ob_end_flush() 就相当于在php.ini中使用output_buffering = false一样,关闭服务器缓存.
基于前面的讨论,我们就有可能使用Ticks来实现,一个无刷新,无ajax的聊天室: 页面中包含俩个iframe,一个是不断获取聊天室的聊天内容,一个包含用户发表聊天内容的form. 这样,在第一个frame的脚本中:
- ob_end_clean();//关闭缓存
- set_time_limit(0);ob_implicit_flush(); //这个语句将强制每当有输出就自动刷新,相当于在每个echo后,调用ob_flush()$new_mesg = NULL;register_tick_function("getNewMesg");declare(ticks=1){while(1){if(!is_null($new_mesg)){foreach($new_mesg as $msg){echo $msg;}$new_mesg = null;}}}function getNewMesg(){//通过查询数据库,或者共享内存,来获取现在的聊天室大厅的内容。//返回一个数组,包含所有的新的聊天内容}
这样就实现了一个简单的使用服务器推技术的聊天室的框架。
当然,关于实时输出,还有一些其他的限制,比如在PHP5手册中讲到的:
个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。
有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。
甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到
标记之前,不会显示出整个表格。
一些版本的 Microsoft Internet Explorer 只有当接受到的256(甚至更多)个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。
接下来,我贴一个很有趣的代码,有兴趣的同学,可以试试:
- header("Content-type: multipart/x-mixed-replace;boundary=endofsection");print "--endofsection\n";$pmt = array("-", "\\", "|", "/" );for( $i = 0; $i <10;$i ++ ){sleep(1);print "Content-type: text/plain\n\n";print "Part $i ".$pmt[$i % 4];print "--endofsection\n";ob_flush(); //强制将缓存区的内容输出flush(); //强制将缓冲区的内容发送给客户端}print "Content-type: text/plain\n\n";print "The end\n";print "–endofsection–\n";
使用firefox打开,看看你看到了什么。
采用PHP实现”服务器推”技术的聊天室的更多相关文章
- 如何使用ASP.NET开发基于推技术的聊天室?
public class Content : System.Web.UI.Page{private void Page_Load(object sender, System.EventArgs e){ ...
- Comet:基于 HTTP 长连接的“服务器推”技术
“服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...
- 转载:Comet:基于 HTTP 长连接的“服务器推”技术
转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客 ...
- [转载] Comet:基于 HTTP 长连接的“服务器推”技术
转载自http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工 ...
- “服务器推”技术【转载+整理】
原文地址 本文内容 "服务器推(server-push)"技术的应用 基于客户端套接口的"服务器推"技术 基于 HTTP 长连接的"服务器推" ...
- Comet:基于 HTTP 长连接的“服务器推”技术(转载)
“服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信 ...
- 【转】Comet:基于 HTTP 长连接的“服务器推”技术
原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无 ...
- Comet:基于 HTTP 长连接的“服务器推”技术解析
原文链接:http://www.cnblogs.com/deepleo/p/Comet.html 一.背景介绍 传统web请求,是显式的向服务器发送http Request,拿到Response后显示 ...
- HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)
反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...
随机推荐
- 转: Laravel的数据库迁移 介绍的比较清晰
原文: https://blog.sbot.io/articles/12/Laravel-数据库迁移(Database-Migrations)操作实例 很多人可能在学习Laravel框架的时候,对La ...
- lvm实现服务器磁盘空间合并
1 LVM实现将2块磁盘总空间“合二为一”并挂载到同一目录 1.1 磁盘分区 首先查看磁盘信息,对未分区的磁盘进行分区处理(选择你要合并的盘,这里是对vdb.vdc). 如上图,可以看出有5 ...
- 本地连接mysql的url写法
一.jdbc:mysql:///中三条斜杠(///) 第三个/代表什么? jdbc:mysql:///testdatabase等同于 jdbc:mysql://localhost:3306/testd ...
- C语言递归之二叉树的最小深度
题目描述 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例 输入:[3,9,20,null,null,15,7] ...
- IDEA如何快速搭建Java开发环境
作为IntelliJ IDEA mac新手,IDEA如何快速搭建Java开发环境呢?今天小编就给大家带来了IntelliJ IDEA mac使用教程,想知道IDEA如何快速搭建Java开发环境? 全局 ...
- UVA750回溯法典例-八皇后
文章代码选自UVA750-8 Queens Chess Problem的部分代码 vj题目链接:https://vjudge.net/problem/UVA-750 由于UVA中要求按照字典序输出,下 ...
- Milestone
为什么开博客? 事情要从一只蝙蝠说起... 准备用博客做什么? 记录自己在开发中遇到的issue以及解决的思路:记录一些读书笔记以便温故:练习如何制造仪式感,ect. ...
- H5_0009:关于HTML5中Canvas的宽、高设置问题
关于HTML5中Canvas的宽.高设置问题 Canvas元素默认宽 300px, 高 150px, 设置其宽高可以使用如下方法(不会被拉伸): 方法一: <canvas widt ...
- css3制作网页动画
一.CSS3变形 CSS3变形是一些效果的集合 如平移.旋转.缩放.倾斜效果 每个效果都可以称为变形(transform),它们可以分别操控元素发生平移.旋转.缩放.倾斜等变化 二.CSS3位移:tr ...
- ACM-ICPC 2018 徐州赛区网络预赛 Ryuji doesn't want to study
简单数学变换+线段树 简单数据结构签到题不解释 本来应该贴板子的,鉴于最近写代码太少了,而且由于要用两个线段树,平时板子都是一个的.以及板子在队友那.就当熟悉写代码,自己写了一下. #include ...