php伺服器推技術的聊天室

來源:互聯網
上載者:User
  1. //chat.php
  2. header('cache-control: private');
  3. header('Content-Type: text/html; charset=utf-8');
  4. ?>
複製代碼

儲存使用者提交的聊天內容簡易版本:

  1. $content = trim($_POST['content']);
  2. if ($content) {
  3. $fp = fopen('./chat.txt', 'a');
  4. fwrite($fp, $content . "\n");
  5. fclose($fp);
  6. clearstatcache();
  7. }
  8. ?>
複製代碼

主要的HTTP長串連部分,chat_content.php檔案:

  1. header('cache-control: private');

  2. header('Content-Type: text/html; charset=utf-8');
  3. //測試設定30秒逾時,一般會設定比較長時間。
  4. set_time_limit(30);
  5. //這一行是為了搞定IE這個BT
  6. echo str_repeat(' ', 256);

  7. ob_flush();

  8. flush();

  9. $fp = new SplFileObject('./chat.txt', 'r+');

  10. $line = 0;
  11. $totalLine = 0;
  12. while (!$fp->eof()) {
  13. $fp->current();
  14. $totalLine++;
  15. $fp->next();
  16. }

  17. $fp->seek($totalLine);

  18. $i = $totalLine - 1;
  19. while (true) {
  20. if (!$fp->eof()) {
  21. if ($content = trim($fp->current())) {
  22. echo '';
  23. echo htmlspecialchars($content);
  24. echo "";
  25. flush();
  26. $fp->next();
  27. $i++;
  28. }
  29. } else {
  30. $fp->seek($i - 1);
  31. $fp->next();
  32. }
  33. {
  34. //這裡可以添加心跳檢測後退出迴圈
  35. }
  36. usleep(1000);
  37. }
  38. ?>

複製代碼

代碼說明:  06. 設定一個逾時時間,由於要保持HTTP長串連,這個時間肯定要比較長,可能要幾個小時吧,上面提到的文章裡也有說明,這種HTTP長串連只能開啟兩個,由於瀏覽器的限制。另外其實即使你設定了一個永不逾時,其實上伺服器部分(如Apache)的設定檔也可能對HTTP請求設定了最長等待時間,所以也可能效果會不是你想的,一般預設可能都是15分鐘逾時。如果有興趣可以自己嘗試修改。

  09. 這裡輸出了一段空白,主要是手冊上已經說明了,IE瀏覽器在前面256個字元是不會直接輸出的,所以我們先隨便輸出些空白,以便讓後面的內容輸出來,可能其他瀏覽器也有其他瀏覽器的設定,具體可以查看PHP手冊的frush函數的說明。接下去11、12行就是強制把這些空白符丟給瀏覽器輸出。

  13. ~ 20. 這裡主要是為了計算檔案行數,以便從這一行後面開始讀內容。

  接下去的while迴圈就是一個死迴圈了,就是迴圈輸出檔案內容,每次判斷是否到達檔案末尾,如果有使用者寫入檔案,則當前檢測肯定不是檔案末尾,就將該行讀取出來輸出,否則將指標往前移動一行,繼續迴圈,每次等待1000微秒,

  39. 如果一直保持長串連,那麼即使用戶端斷開,服務端也不一定能知道用戶端已經斷開,所以這裡可能還需要做一些心跳記錄,比如每個使用者保持一個心跳flag,每格幾秒更新一下最後心跳時間,當檢測最後時間很久沒更新後,推出這個死迴圈,關閉這個HTTP串連。

示範樣本2:傳統的B/S結構的應用程式,都是採用\"用戶端拉\"結束來實現用戶端和伺服器端的資料交換。 本文將通過結合Ticks,來實現一個伺服器推的PHP聊天室簡單構想。

PHPer,尤其是用過set_cookie, header的,一定見過這樣的提示資訊:\"Warning: Cannot modify header information - headers already sent by.....\", 這是因為通過HTTP協議通訊,資料包會包含倆個部分,一個是Header,一個是data。一般來說,都是先Header部分,在Heaer部分指明了Data部分的長度,然後使用\\r\\n\\r\\n來表示header部分結束,接下來是Data部分。

當有任何輸出時,Header部分就發送了,此時,再想header函數來改變一些Header部分的域資訊,就會得到上面的提示資訊。 一個簡單的辦法就是使用output_buffering。讓它來快取服務器的輸出,不要太早將Header部分發給用戶端。 那麼,如果不使用output_buffering,是不是就可以實現,每當伺服器有輸出,就立即發送給用戶端呢? 做個如下實驗:

  1. //設定php.ini中output_buffering=0 或者使用ob_end_flush()關閉緩衝
  2. set_time_limit(0);
  3. for($i=0;$i<10;$i++){
  4. echo \"Now Index is :\". $i;
  5. sleep(1);
  6. }
  7. ?>
複製代碼

結果發現,還是要等到指令碼全部執行完以後,才能一次看到所有的結果。為什麼呢? 這是因為只是解決了緩衝問題,但是還有一個緩衝問題,PHP會緩衝程式的輸出。所以,此時還需要調用,flush(), 來強制使得PHP將所有的程式輸出發送給用戶端。

  1. //設定php.ini中output_buffering=0

  2. ob_end_flush();//關閉緩衝

  3. set_time_limit(0);

  4. for($i=0;$i<10;$i++){
  5. echo \"Now Index is :\". $i;
  6. flush();
  7. sleep(1);
  8. }
  9. ?>

複製代碼

現在是不是看到了,不斷有伺服器的資料顯示出來?

有幾個概念之間的關係,這裡補充下: 在代碼中使用ob_start(), 就相當於在php.ini中使用output_buffering=on一樣,使用伺服器緩衝。 在代碼中使用ob_end_flush() 就相當於在php.ini中使用output_buffering = false一樣,關閉伺服器緩衝。 1 2 下一頁 尾頁

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.