基于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 相关文章推荐
ThinkPHP验证码使用简明教程
Mar 05 PHP
destoon实现VIP排名一直在前面排序的方法
Aug 21 PHP
php数组查找函数总结
Nov 18 PHP
php简单的上传类分享
May 15 PHP
php多线程并发实现方法
Sep 30 PHP
CI框架数据库查询缓存优化的方法
Nov 21 PHP
PHP面向对象程序设计组合模式与装饰模式详解
Dec 02 PHP
php使用curl下载指定大小的文件实例代码
Sep 30 PHP
浅析PHP中的闭包和匿名函数
Dec 25 PHP
PHP观察者模式示例【Laravel框架中有用到】
Jun 15 PHP
Laravel框架实现的使用smtp发送邮件功能示例
Mar 12 PHP
Yii使用EasyWechat实现小程序获取用户的openID的方法
Apr 29 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
phpBB BBcode处理的漏洞
2006/10/09 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
2014/08/08 PHP
php求今天、昨天、明天时间戳的简单实现方法
2016/07/28 PHP
基于PHP实现微信小程序客服消息功能
2019/08/12 PHP
任意位置显示html菜单
2007/02/01 Javascript
Javascript &amp; DHTML 实例编程(教程)(三)初级实例篇1—上传文件控件实例
2007/06/02 Javascript
jQuery 菜单随滚条改为以定位方式(固定要浏览器顶部)
2012/05/24 Javascript
javascript刷新父页面的各种方法汇总
2014/09/03 Javascript
jquery+CSS3实现淘宝移动网页菜单效果
2015/08/31 Javascript
JavaScript预解析及相关技巧分析
2016/04/21 Javascript
JS输出空格的简单实现方法
2016/09/08 Javascript
Angularjs 创建可复用组件实例代码
2016/10/09 Javascript
利用jquery禁止外层滚动条的滚动
2017/01/05 Javascript
bootstrap Validator 模态框、jsp、表单验证 Ajax提交功能
2017/02/17 Javascript
AngularJS 控制器 controller的详解
2017/10/17 Javascript
vue.js input框之间赋值方法
2018/08/24 Javascript
Vue的双向数据绑定实现原理解析
2020/02/17 Javascript
js+canvas实现简单扫雷小游戏
2021/01/22 Javascript
koa2的中间件功能及应用示例
2020/03/05 Javascript
Python中with及contextlib的用法详解
2017/06/08 Python
python使用tensorflow深度学习识别验证码
2018/04/03 Python
使用python编写监听端
2018/04/12 Python
Python基础教程之异常详解
2019/01/10 Python
PySide和PyQt加载ui文件的两种方法
2019/02/27 Python
Python使用LDAP做用户认证的方法
2019/06/20 Python
Win10 安装PyCharm2019.1.1(图文教程)
2019/09/29 Python
Python3打包exe代码2种方法实例解析
2020/02/17 Python
Python PyQt5模块实现窗口GUI界面代码实例
2020/05/12 Python
Zavvi西班牙:电子游戏、极客服装、Blu-ray、Funko Pop等
2019/05/03 全球购物
银行求职推荐信范文
2013/11/30 职场文书
优秀中学生事迹材料
2014/01/31 职场文书
万里长城导游词
2015/01/30 职场文书
团员个人年度总结
2015/02/26 职场文书
退休欢送会致辞
2015/07/31 职场文书
导游词幽默开场白
2019/06/26 职场文书
Nginx虚拟主机的配置步骤过程全解
2022/03/31 Servers