基于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 相关文章推荐
简单示例AJAX结合PHP代码实现登录效果代码
Jul 25 PHP
php.ini-dist 和 php.ini-recommended 的区别介绍(方便开发与安全的朋友)
Jul 01 PHP
zend framework配置操作数据库实例分析
Dec 06 PHP
php合并数组中相同元素的方法
Nov 13 PHP
php去除html标记的原生函数详解
Jan 27 PHP
在openSUSE42.1下编译安装PHP7 的方法
Dec 24 PHP
laravel中的错误与日志用法详解
Jul 26 PHP
PHP MYSQL简易交互式站点开发
Dec 27 PHP
php+mysql+jquery实现日历签到功能
Feb 27 PHP
php实现socket推送技术的示例
Dec 20 PHP
PHP递归统计系统中代码行数
Sep 19 PHP
Laravel5.3+框架定义API路径取消CSRF保护方法详解
Apr 06 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
PHP 之Section与Cookie使用总结
2012/09/14 PHP
Mac环境下php操作mysql数据库的方法分享
2015/05/11 PHP
php中strlen和mb_strlen用法实例分析
2016/11/12 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
2017/07/20 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
javascript中的array数组使用技巧
2010/01/31 Javascript
JavaScript 编写匿名函数的几种方法
2010/02/21 Javascript
B/S模式项目中常用的javascript汇总
2013/12/17 Javascript
js数字转换为float,取N位小数
2014/02/08 Javascript
PHP守护进程实例
2015/03/06 Javascript
jQuery创建自定义的选择器用以选择高度大于100的超链接实例
2015/03/18 Javascript
javascript数组随机排序实例分析
2015/07/22 Javascript
javascript数字验证的实例代码(推荐)
2016/08/20 Javascript
ES6 Generator函数的应用实例分析
2019/06/26 Javascript
微信小程序模板消息限制实现无限制主动推送的示例代码
2019/08/27 Javascript
layui使用表格渲染获取行数据的例子
2019/09/13 Javascript
python Django连接MySQL数据库做增删改查
2013/11/07 Python
Python中的fileinput模块的简单实用示例
2015/07/09 Python
Python基于OpenCV库Adaboost实现人脸识别功能详解
2018/08/25 Python
详解python数据结构和算法
2019/04/18 Python
python多线程扫描端口(线程池)
2019/09/04 Python
pycharm激活码快速激活及使用步骤
2020/03/12 Python
Python无头爬虫下载文件的实现
2020/04/02 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
基于Python绘制个人足迹地图
2020/06/01 Python
Python filter过滤器原理及实例应用
2020/08/18 Python
Python pip 常用命令汇总
2020/10/19 Python
CSS3动画:5种预载动画效果实例
2017/04/05 HTML / CSS
Linux中如何用命令创建目录
2015/01/12 面试题
四种会话跟踪技术
2015/05/20 面试题
面料业务员岗位职责
2013/12/26 职场文书
家长对小学生的评语
2014/01/28 职场文书
煤矿机修工岗位职责
2014/02/07 职场文书
委托书格式范文
2015/01/28 职场文书
小学生五一劳动节演讲稿
2015/03/18 职场文书