请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

Endige-新锐工作室

 找回密码
 立即注册

用新浪微博连接

一步搞定

QQ登录

只需一步,快速开始

查看: 3955|回复: 0

基于HTTP长连接的"服务器推"技术的php 简易聊天室 [复制链接]

Rank: 2

威望
0
金钱
43
贡献
0
新豆
0
最后登录
1970-1-1
注册时间
2011-11-23
精华
0
积分
52
阅读权限
20
帖子
9
发表于 2011-11-29 20:28:04 |显示全部楼层
本帖最后由 louis 于 2011-11-29 20:28 编辑

首先是首页,包含一个文本输入和一个显示聊天内容的iframe,还有一个隐藏iframe用来提交form表单:
  1. <?php
  2. //chat.php
  3. header('cache-control: private');
  4. header('Content-Type: text/html; charset=utf-8');
  5. ?>
  6. <html>
  7. <script type="text/javascript">
  8. function submitChat(obj) {
  9. obj.submit();
  10. document.getElementsByName('content')[0].value = '';
  11. }
  12. </script>
  13. <iframe src="./chat_content.php" height="300" width="100%"></iframe>
  14. <iframe name="say" height="0" width="0"></iframe>
  15. <form method="POST" target="say" action="./say.php">
  16. <input type="text" size="30" name="content" /> <input type="button" value="say" />
  17. </form>
  18. </html>

另外一个就是保存用户提交的聊天内容了,我简单的写一下文本,而且没有做什么锁定,这个只是简易版本:
  1. <?php
  2. $content = trim($_POST['content']);
  3. if ($content) {
  4. $fp = fopen('./chat.txt', 'a');
  5. fwrite($fp, $content . "\n");
  6. fclose($fp);
  7. clearstatcache();
  8. }
  9. ?>

接下来看主要的HTTP长连接部分,也就是chat_content.php文件:
  1. <?php
  2. header('cache-control: private');
  3. header('Content-Type: text/html; charset=utf-8');
  4. //测试设置30秒超时,一般会设置比较长时间。
  5. set_time_limit(30);
  6. //这一行是为了搞定IE这个BT
  7. echo str_repeat(' ', 256);
  8. ob_flush();
  9. flush();
  10. $fp = new SplFileObject('./chat.txt', 'r+');
  11. $line = 0;
  12. $totalLine = 0;
  13. while (!$fp->eof()) {
  14. $fp->current();
  15. $totalLine++;
  16. $fp->next();
  17. }
  18. $fp->seek($totalLine);
  19. $i = $totalLine - 1;
  20. while (true) {
  21. if (!$fp->eof()) {
  22. if ($content = trim($fp->current())) {
  23. echo '<div>';
  24. echo htmlspecialchars($content);
  25. echo "</div>";
  26. flush();
  27. $fp->next();
  28. $i++;
  29. }
  30. } else {
  31. $fp->seek($i - 1);
  32. $fp->next();
  33. }
  34. {
  35. //这里可以添加心跳检测后退出循环
  36. }
  37. usleep(1000);
  38. }
  39. ?>

我一行行解释一下,其实也比较容易理解:
  06. 设置一个超时时间,由于要保持HTTP长连接,这个时间肯定要比较长,可能要几个小时吧,上面提到的文章里也有说明,这种HTTP长连接只能打开两个,由于浏览器的限制。另外其实即使你设置了一个永不超时,其实上服务器部分(如Apache)的配置文件也可能对HTTP请求设置了最长等待时间,所以也可能效果会不是你想的,一般默认可能都是15分钟超时。如果有兴趣可以自己尝试修改。
  09. 这里输出了一段空白,主要是手册上已经说明了,IE浏览器在前面256个字符是不会直接输出的,所以我们先随便输出些空白,以便让后面的内容输出来,可能其他浏览器也有其他浏览器的设置,具体可以查看PHP手册的frush函数的说明。接下去11、12行就是强制把这些空白符丢给浏览器输出。
  13. ~ 20. 这里主要是为了计算文件行数,以便从这一行后面开始读内容。
  接下去的while循环就是一个死循环了,就是循环输出文件内容,每次判断是否到达文件末尾,如果有用户写入文件,则当前检测肯定不是文件末尾,就将该行读取出来输出,否则将指针往前移动一行,继续循环,每次等待1000微秒,
  39. 如果一直保持长连接,那么即使客户端断开,服务端也不一定能知道客户端已经断开,所以这里可能还需要做一些心跳记录,比如每个用户保持一个心跳flag,每格几秒更新一下最后心跳时间,当检测最后时间很久没更新后,推出这个死循环,关闭这个HTTP连接。
  OK,基本上原理就是这样了,当然这个性能不清楚,有兴趣的自己试试,欢迎交流。
您需要登录后才可以回帖 登录 | 立即注册

馨然玫瑰花茶

Archiver|手机版|Endige Inc   

GMT+8, 2017-9-26 22:35 , Processed in 0.045205 second(s), 13 queries .

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部