基于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 相关文章推荐
我的论坛源代码(九)
Oct 09 PHP
PHP聊天室技术
Oct 09 PHP
php操作sqlserver关于时间日期读取的小小见解
Nov 29 PHP
php设计模式 Factory(工厂模式)
Jun 26 PHP
PHP判断远程url是否有效的几种方法小结
Oct 08 PHP
PHP遍历某个目录下的所有文件和子文件夹的实现代码
Jun 28 PHP
教你如何使用php session
Oct 28 PHP
PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
Jul 28 PHP
PHP学习笔记(一) 简单了解PHP
Aug 04 PHP
php中html_entity_decode实现HTML实体转义
Jun 13 PHP
php使用json-schema模块实现json校验示例
Sep 28 PHP
laravel 错误处理,接口错误返回json代码
Oct 25 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调用Oracle存储过程的方法
2008/09/12 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHP实现的交通银行网银在线支付接口ECSHOP插件和使用例子
2014/05/10 PHP
Discuz7.2版的faq.php SQL注入漏洞分析
2014/08/06 PHP
php随机生成数字字母组合的方法
2015/03/18 PHP
PHP处理bmp格式图片的方法分析
2017/07/04 PHP
PHP实现求解最长公共子串问题的方法
2017/11/17 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
2020/06/02 PHP
jQuery在IE下使用未闭合的xml代码创建元素时的Bug介绍
2012/01/10 Javascript
如何用js控制frame的隐藏或显示的解决办法
2013/03/20 Javascript
上传的js验证(图片/文件的扩展名)
2013/04/25 Javascript
不同Jquery版本引发的问题解决
2013/10/14 Javascript
原生javascript实现无间缝滚动示例
2014/01/28 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
jQuery窗口、文档、网页各种高度的精确理解
2014/07/02 Javascript
Javascript 读取操作Sql中的Xml字段
2014/10/09 Javascript
js点击按钮实现带遮罩层的弹出视频效果
2015/12/19 Javascript
js获取对象、数组的实际长度,元素实际个数的实现代码
2016/06/08 Javascript
ionic环境配置及问题详解
2017/06/27 Javascript
vue基础之使用get、post、jsonp实现交互功能示例
2019/03/12 Javascript
python基础教程之字典操作详解
2014/03/25 Python
在Python的Flask框架中验证注册用户的Email的方法
2015/09/02 Python
python模块之re正则表达式详解
2017/02/03 Python
Python 绘图和可视化详细介绍
2017/02/11 Python
Python实现二维曲线拟合的方法
2018/12/29 Python
使用Python操作ArangoDB的方法步骤
2020/02/02 Python
Pythonic版二分查找实现过程原理解析
2020/08/11 Python
HTML5 video标签(播放器)学习笔记(二):播放控制
2015/04/24 HTML / CSS
毕业生教师求职信
2013/10/20 职场文书
精细化工应届生求职信
2013/11/17 职场文书
元旦晚会策划方案
2014/02/18 职场文书
幼儿园教师教育感言
2014/02/28 职场文书
五年级小学生评语
2014/12/26 职场文书
vue引入Excel表格插件的方法
2021/04/28 Vue.js
Python+DeOldify实现老照片上色功能
2022/06/21 Python
mysql通过group by分组取最大时间对应数据的两种有效方法
2022/09/23 MySQL