採用PHP實現”伺服器推”技術的聊天室

來源:互聯網
上載者:User

   傳統的B/S結構的應用程式,都是採用"用戶端拉"結束來實現用戶端和伺服器端的資料交換。
  本文將通過結合Ticks(可以參看我的另外一篇文章:關於PHP你可能不知道的-PHP的事件驅動化設計 ),來實現一個伺服器推的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,是不是就可以實現,每當伺服器有輸出,就立即發送給用戶端呢?

   做個如下實驗:

//設定php.ini中output_buffering=0 或者使用ob_end_flush()關閉緩衝

set_time_limit(0);
for($i=0;$i<10;$i++){
  echo "Now Index is :". $i;
  sleep(1);
}

 

  結果我們發現,還是要等到指令碼全部執行完以後,才能一次看到所有的結果。。

 

  為什麼呢?

 

  這是因為我們只是解決了緩衝問題,但是還有一個緩衝問題,PHP會緩衝程式的輸出。所以,這個時候,我們還需要調用,flush(), 來強制使得PHP將所有的程式輸出發送給用戶端。

//設定php.ini中output_buffering=0
ob_end_flush();//關閉緩衝

set_time_limit(0);
for($i=0;$i&lt;10;$i++){
  echo "Now Index is :". $i;
  flush();
  sleep(1);
}

 

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

 

    有幾個概念之間的關係,我這裡補充以下:

 

    在代碼中使用ob_start(), 就相當於在php.ini中使用output_buffering=on一樣,使用伺服器緩衝。

 

    在代碼中使用ob_end_flush() 就相當於在php.ini中使用output_buffering = false一樣,關閉伺服器緩衝。

 

   

 

     基於前面的討論,我們就有可能使用Ticks來實現,一個無重新整理,無ajax的聊天室: 頁面中包含倆個iframe,一個是不斷擷取聊天室的聊天內容,一個包含使用者發表聊天內容的form. 這樣,在第一個frame的指令碼中:


ob_end_clear();//關閉緩衝
set_time_limit(0);
ob_implicit_flush(); //這個語句將強制每當有輸出就自動重新整理,相當於在每個echo後,調用flush()
$new_mesg = NULL;
register_tick_function("getNewMesg");
declare(ticks=1){
  while(1){
     if(!is_null($new_mesg)){
          foreach($new_mesg as $msg){
                echo $msg;
          }
          $new_mesg = null;
     }     
  }
}

function getNewMesg(){
//通過查詢資料庫,或者共用記憶體,來擷取現在的聊天室大廳的內容。
//返回一個數組,包含所有的新的聊天內容
}

 

 這樣就實現了一個簡單的使用伺服器推技術的聊天室的架構。

 

 當然,關於即時輸出,還有一些其他的限制,比如在PHP5手冊中講到的:

 

個別web伺服器程式,特別是Win32下的web伺服器程式,在發送結果到瀏覽器之前,仍然會緩衝指令碼的輸出,直到程式結束為止。

有些Apache的模組,比如mod_gzip,可能自己進行輸出緩衝,這將導致flush()函數產生的結果不會立即被發送到用戶端瀏覽器。

甚至瀏覽器也會在顯示之前,緩衝接收到的內容。例如 Netscape 瀏覽器會在接受到換行或 html 標記的開頭之前緩衝內容,並且在接受到 &lt;/table> 標記之前,不會顯示出整個表格。

一些版本的 Microsoft Internet Explorer 只有當接受到的256個位元組以後才開始顯示該頁面,所以必鬚髮送一些額外的空格來讓這些瀏覽器顯示頁面內容。

 

 接下來,我貼一個很有趣的代碼,有興趣的同學,可以試試:


header(‘Content-type: multipart/x-mixed-replace;boundary=endofsection‘);
print " –endofsection ";
$pmt = array("-", "/", "|", "/" );
for( $i = 0; $i &lt;10;$i ++ )
{
        sleep(1);
        print "Content-type: text/plain ";
        print "Part $i ".$pmt[$i % 4];
        print "–endofsection ";
        ob_flush(); //強制將緩衝區的內容輸出
        flush(); //強制將緩衝區的內容發送給用戶端
}
print "Content-type: text/plain ";
print "The end ";
print "–endofsection– ";

  使用firefox開啟,看看你看到了什麼。

 

  這個例子,使用了ob_flush(), 這樣可以在代碼中控制緩衝區內容的輸出時機,更加靈活一些。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.