首頁  >  文章  >  後端開發  >  基於HTTP長連線的"伺服器推"技術的php 簡易聊天室

基於HTTP長連線的"伺服器推"技術的php 簡易聊天室

PHPz
PHPz原創
2016-07-29 08:41:021085瀏覽

關於HTTP長連接的「伺服器推」技術原理可以查看IBM的這篇文章,我簡單的做了個DEMO.

首先是首頁,包含一個文字輸入和一個顯示聊天內容的iframe,還有一個隱藏iframe用來提交form表單:

程式碼如下:

<?php
//chat.php
header(&#39;cache-control: private&#39;);
header(&#39;Content-Type: text/html; charset=utf-8&#39;);
?>
<html>
<script type="text/javascript">
function submitChat(obj) {
obj.submit();
document.getElementsByName(&#39;content&#39;)[0].value = &#39;&#39;;
}
</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[&#39;content&#39;]);
if ($content) {
$fp = fopen(&#39;./chat.txt&#39;, &#39;a&#39;);
fwrite($fp, $content . "\n");
fclose($fp);
clearstatcache();
}
?>

接下來看主要的HTTP長連結部分,也就是chat_content.php檔:

程式碼如下:

<?php
header(&#39;cache-control: private&#39;);
header(&#39;Content-Type: text/html; charset=utf-8&#39;);
//测试设置30秒超时,一般会设置比较长时间。
set_time_limit(30);
//这一行是为了搞定IE这个BT
echo str_repeat(&#39; &#39;, 256);
ob_flush();
flush();
$fp = new SplFileObject(&#39;./chat.txt&#39;, &#39;r+&#39;);
$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 &#39;<div>&#39;;
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連線。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn