基于HTTP长连接的"服务器推"技术的php 简易聊天室


Posted in PHP onOctober 31, 2009

首先是首页,包含一个文本输入和一个显示聊天内容的iframe,还有一个隐藏iframe用来提交form表单:

<?php 
//chat.php 
header('cache-control: private'); 
header('Content-Type: text/html; charset=utf-8'); 
?> 
<html> 
<script type="text/javascript"> 
function submitChat(obj) { 
obj.submit(); 
document.getElementsByName('content')[0].value = ''; 
} 
</script> 
<iframe src="./chat_content.php" height="300" width="100%"></iframe> 
<iframe name="say" height="0" width="0"></iframe> 
<form method="POST" target="say" action="./say.php" onsubmit="submitChat(this)"> 
<input type="text" size="30" name="content" /> <input type="button" value="say" onclick="submitChat(this.form)" /> 
</form> 
</html>

另外一个就是保存用户提交的聊天内容了,我简单的写一下文本,而且没有做什么锁定,这个只是简易版本:
<?php 
$content = trim($_POST['content']); 
if ($content) { 
$fp = fopen('./chat.txt', 'a'); 
fwrite($fp, $content . "\n"); 
fclose($fp); 
clearstatcache(); 
} 
?>

接下来看主要的HTTP长连接部分,也就是chat_content.php文件:

<?php 
header('cache-control: private'); 
header('Content-Type: text/html; charset=utf-8'); 
//测试设置30秒超时,一般会设置比较长时间。 
set_time_limit(30); 
//这一行是为了搞定IE这个BT 
echo str_repeat(' ', 256); 
ob_flush(); 
flush(); 
$fp = new SplFileObject('./chat.txt', 'r+'); 
$line = 0; 
$totalLine = 0; 
while (!$fp->eof()) { 
$fp->current(); 
$totalLine++; 
$fp->next(); 
} 
$fp->seek($totalLine); 
$i = $totalLine - 1; 
while (true) { 
if (!$fp->eof()) { 
if ($content = trim($fp->current())) { 
echo '<div>'; 
echo htmlspecialchars($content); 
echo "</div>"; 
flush(); 
$fp->next(); 
$i++; 
} 
} else { 
$fp->seek($i - 1); 
$fp->next(); 
} 
{ 
//这里可以添加心跳检测后退出循环 
} 
usleep(1000); 
} 
?>

我一行行解释一下,其实也比较容易理解:

06. 设置一个超时时间,由于要保持HTTP长连接,这个时间肯定要比较长,可能要几个小时吧,上面提到的文章里也有说明,这种HTTP长连接只能打开两个,由于浏览器的限制。另外其实即使你设置了一个永不超时,其实上服务器部分(如Apache)的配置文件也可能对HTTP请求设置了最长等待时间,所以也可能效果会不是你想的,一般默认可能都是15分钟超时。如果有兴趣可以自己尝试修改。

09. 这里输出了一段空白,主要是手册上已经说明了,IE浏览器在前面256个字符是不会直接输出的,所以我们先随便输出些空白,以便让后面的内容输出来,可能其他浏览器也有其他浏览器的设置,具体可以查看PHP手册的frush函数的说明。接下去11、12行就是强制把这些空白符丢给浏览器输出。

13. ~ 20. 这里主要是为了计算文件行数,以便从这一行后面开始读内容。

接下去的while循环就是一个死循环了,就是循环输出文件内容,每次判断是否到达文件末尾,如果有用户写入文件,则当前检测肯定不是文件末尾,就将该行读取出来输出,否则将指针往前移动一行,继续循环,每次等待1000微秒,

39. 如果一直保持长连接,那么即使客户端断开,服务端也不一定能知道客户端已经断开,所以这里可能还需要做一些心跳记录,比如每个用户保持一个心跳flag,每格几秒更新一下最后心跳时间,当检测最后时间很久没更新后,推出这个死循环,关闭这个HTTP连接。

OK,基本上原理就是这样了,当然这个性能不清楚,有兴趣的自己试试,欢迎交流。

PHP 相关文章推荐
WindowsXP中快速配置Apache+PHP5+Mysql
Jun 05 PHP
php 动态添加记录
Mar 10 PHP
UCenter中的一个可逆加密函数authcode函数代码
Jul 20 PHP
Linux Apache PHP Oracle 安装配置(具体操作步骤)
Jun 17 PHP
php+mysqli使用面向对象方式更新数据库实例
Jan 29 PHP
php中smarty模板条件判断用法实例
Jun 11 PHP
YiiFramework入门知识点总结(图文教程)
Dec 28 PHP
微信支付扫码支付php版
Jul 22 PHP
Yii2实现UploadedFile上传文件示例
Feb 15 PHP
php之header的不同用法总结(实例讲解)
Nov 28 PHP
PHP自动生成缩略图函数的源码示例
Mar 18 PHP
Laravel框架集合用法实例浅析
May 14 PHP
php UTF8 文件的签名问题
Oct 30 #PHP
PHP+MySQL 手工注入语句大全 推荐
Oct 30 #PHP
php 攻击方法之谈php+mysql注射语句构造
Oct 30 #PHP
PHP 文件上传源码分析(RFC1867)
Oct 30 #PHP
浅谈PHP 闭包特性在实际应用中的问题
Oct 30 #PHP
php实现jQuery扩展函数
Oct 30 #PHP
PHP 读取和修改大文件的某行内容的代码
Oct 30 #PHP
You might like
手把手教你使用DedeCms的采集的图文教程
2007/03/11 PHP
php入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
2011/07/14 PHP
PHP设计模式之装饰者模式代码实例
2015/05/11 PHP
PHP切割整数工具类似微信红包金额分配的思路详解
2019/09/18 PHP
php 输出缓冲 Output Control用法实例详解
2020/03/03 PHP
用javascript实现读取txt文档的脚本
2007/07/20 Javascript
JavaScript Event学习第二章 Event浏览器兼容性
2010/02/07 Javascript
基于jQuery的弹出消息插件 DivAlert之旅(一)
2010/04/01 Javascript
extjs之去除s.gif的影响
2010/12/25 Javascript
jQuery UI AutoComplete 使用说明
2011/06/20 Javascript
jQuery中使用Ajax获取JSON格式数据示例代码
2013/11/26 Javascript
jQuery遍历Table应用示例
2014/04/09 Javascript
js函数模拟显示桌面.scf程序示例
2014/04/20 Javascript
javascript模拟post提交隐藏地址栏的参数
2014/09/03 Javascript
微信小程序 swiper组件轮播图详解及实例
2016/11/16 Javascript
JavaScript解析JSON格式数据的方法示例
2017/01/24 Javascript
js和jquery中获取非行间样式
2017/05/05 jQuery
jQuery用户头像裁剪插件cropbox.js使用详解
2017/06/07 jQuery
微信小程序 获取二维码实例详解
2017/06/23 Javascript
JavaScript实现图片本地预览功能【不用上传至服务器】
2017/09/20 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
Angular2开发环境搭建教程之VS Code
2017/12/15 Javascript
Vue路由切换时的左滑和右滑效果示例
2018/05/29 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
vue实现点击按钮切换背景颜色的示例代码
2020/06/23 Javascript
vue 出现data-v-xxx的原因及解决
2020/08/04 Javascript
Python yield 小结和实例
2014/04/25 Python
matplotlib subplots 调整子图间矩的实例
2018/05/25 Python
python中ASCII码字符与int之间的转换方法
2018/07/09 Python
python使用matplotlib绘制雷达图
2019/10/18 Python
python包的导入方式总结
2021/03/02 Python
快时尚眼镜品牌,全国连锁眼镜店:LOHO眼镜生活
2018/10/08 全球购物
营销主管自我评价怎么写
2013/09/19 职场文书
法律工作求职自荐信
2013/10/31 职场文书
幼儿园大班教育随笔
2015/08/14 职场文书
2016高三毕业赠言寄语
2015/12/04 职场文书