基于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 相关文章推荐
BBS(php &amp; mysql)完整版(六)
Oct 09 PHP
用php来检测proxy
Oct 09 PHP
php正则校验用户名介绍
Jul 19 PHP
Smarty Foreach 使用说明
Mar 23 PHP
PHP发明人谈MVC和网站设计架构 貌似他不支持php用mvc
Jun 04 PHP
百万级别知乎用户数据抓取与分析之PHP开发
Sep 28 PHP
PHP基于PDO实现的SQLite操作类【包含增删改查及事务等操作】
Jun 21 PHP
详解PHP防止直接访问.php 文件的实现方法
Jul 28 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
Aug 28 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
Sep 22 PHP
php实现在线考试系统【附源码】
Sep 18 PHP
PHP封装的page分页类定义与用法完整示例
Dec 24 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实现多维数组转字符串和多维数组转一维数组的方法
2015/08/08 PHP
PHP加密解密类实例代码
2016/07/20 PHP
ThinkPHP 5.x远程命令执行漏洞复现
2019/09/23 PHP
PHP中abstract(抽象)、final(最终)和static(静态)原理与用法详解
2020/06/05 PHP
PHP延迟静态绑定使用方法实例解析
2020/09/05 PHP
javascript读取RSS数据
2007/01/20 Javascript
jQuery中filter(),not(),split()使用方法
2010/07/06 Javascript
javascript对talbe进行动态添加、删除、验证实现代码
2012/03/29 Javascript
javascript限制文本框只允许输入数字(曾经与现在的方法对比)
2013/01/18 Javascript
JS继承--原型链继承和类式继承
2013/04/08 Javascript
Extjs NumberField后面加单位实现思路
2013/07/30 Javascript
web网页按比例显示图片实现原理及js代码
2013/08/09 Javascript
js实现在字符串中提取数字
2013/11/05 Javascript
Jquery插件实现点击获取验证码后60秒内禁止重新获取
2015/03/13 Javascript
浅析JavaScript回调函数应用
2016/05/22 Javascript
全面解析jQuery $(document).ready()和JavaScript onload事件
2016/06/08 Javascript
vue.js入门教程之计算属性
2016/09/01 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
2016/11/10 Javascript
快速入门Vue
2016/12/19 Javascript
js遍历添加栏目类添加css 再点击其它删除css【推荐】
2018/06/12 Javascript
4个顶级JavaScript高级文本编辑器
2018/10/10 Javascript
koa2实现登录注册功能的示例代码
2018/12/03 Javascript
SpringBoot在yml配置文件中配置druid的操作
2020/11/16 Javascript
[01:52]2020年DOTA2 TI10夏季活动预告片
2020/07/15 DOTA
[49:21]完美世界DOTA2联赛循环赛 Ink Ice vs LBZS BO2第二场 11.05
2020/11/06 DOTA
探究数组排序提升Python程序的循环的运行效率的原因
2015/04/01 Python
Python3读取文件常用方法实例分析
2015/05/22 Python
Python测试人员需要掌握的知识
2018/02/08 Python
Python 输出时去掉列表元组外面的方括号与圆括号的方法
2018/12/24 Python
基于Python3读写INI配置文件过程解析
2020/07/23 Python
Python实现EM算法实例代码
2020/10/04 Python
投资建议书模板
2014/05/12 职场文书
创文明城市标语
2014/06/16 职场文书
2014年国庆标语
2014/06/30 职场文书
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python
python设置 matplotlib 正确显示中文的四种方式
2021/05/10 Python