基于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 相关文章推荐
用php+mysql一个名片库程序
Oct 09 PHP
php xml文件操作实现代码(二)
Mar 20 PHP
php 3行代码的分页算法(求起始页和结束页)
Oct 21 PHP
修改apache配置文件去除thinkphp url中的index.php
Jan 17 PHP
php遍历类中包含的所有元素的方法
May 12 PHP
php数组生成html下拉列表的方法
Jul 20 PHP
Zend Framework实现留言本分页功能(附demo源码下载)
Mar 22 PHP
php实现登录tplink WR882N获取IP和重启的方法
Jul 20 PHP
ThinkPHP下表单令牌错误与解决方法分析
May 20 PHP
PHP 访问数据库配置通用方法(json)
May 20 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
Apr 15 PHP
php查询内存信息操作示例
May 09 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
《雄兵连》《烈阳天道》真的来了
2020/07/13 国漫
PHP CURL模拟登录新浪微博抓取页面内容 基于EaglePHP框架开发
2012/01/16 PHP
关于PHP堆栈与列队的学习
2013/06/21 PHP
php中__destruct与register_shutdown_function执行的先后顺序问题
2014/10/17 PHP
php array_values 返回数组的值实例详解
2016/11/17 PHP
PHP实现财务审核通过后返现金额到客户的功能
2019/07/04 PHP
PHP接入微信H5支付的方法示例
2019/10/28 PHP
jQuery 加上最后自己的验证
2009/11/04 Javascript
jquery.pagination.js 无刷新分页实现步骤分享
2012/05/23 Javascript
用按钮控制iframe显示的网页实现方法
2013/02/04 Javascript
控制文字内容的显示与隐藏示例
2014/06/11 Javascript
js获取元素的外链样式的简单实现方法
2016/06/06 Javascript
Node.js 文件夹目录结构创建实例代码
2016/07/08 Javascript
javascript鼠标滑过显示二级菜单特效
2020/11/18 Javascript
详解Angular 4.x NgIf 的用法
2017/05/22 Javascript
详解使用React进行组件库开发
2018/02/06 Javascript
解决layui 复选框等内置控件不显示的问题
2018/08/14 Javascript
vue加载完成后的回调函数方法
2018/09/07 Javascript
vue实现日历备忘录功能
2020/09/24 Javascript
优雅的使用javascript递归画一棵结构树示例代码
2019/09/22 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
python中文乱码的解决方法
2013/11/04 Python
Python解决N阶台阶走法问题的方法分析
2017/12/28 Python
Python通用循环的构造方法实例分析
2018/12/19 Python
Python简单处理坐标排序问题示例
2019/07/11 Python
用Python画小女孩放风筝的示例
2019/11/23 Python
Python数据结构dict常用操作代码实例
2020/03/12 Python
长辈证婚人证婚词
2014/01/09 职场文书
不拖欠农民工工资承诺书
2014/03/31 职场文书
教师对学生的寄语
2014/04/03 职场文书
优秀员工评优方案
2014/06/13 职场文书
交通志愿者活动总结
2014/06/27 职场文书
计划生育诚信协议书
2014/11/02 职场文书
离婚案件被告代理词
2015/05/23 职场文书
2016新年问候语大全
2015/11/11 职场文书
Golang生成Excel文档的方法步骤
2021/06/09 Golang