HTTP長串連伺服器端推技術
收藏
新一篇: 使用 .NET 實現 Ajax 長串連 |
舊一篇: 使用 jQuery 簡化 Ajax 開發
伺服器推送(Server Push)
推送技術的基礎思想是將瀏覽器主動查詢資訊改為伺服器主動發送資訊。伺服器發送一批資料,瀏覽器顯示這些資料,同時保證與伺服器的串連。當伺服器需要再次發送一批資料時,瀏覽器顯示資料並保持串連。以後,伺服器仍然可以發送批量資料,瀏覽器繼續顯示資料,依次類推。
用戶端拉曳(Client Pull)
在用戶端拖曳技術中,伺服器發送一批資料,在HTTP響應或文檔頭標記中插入指令,讓瀏覽器“在5秒內再次裝入這些資料”或“10秒內前往某URL裝入資料”。當指定的時間達到時,用戶端就按照伺服器的指示去做,或者重新整理當前資料,或者調入新的資料。
其實push 和 pull 這兩種技術手段非常不同,但目的幾乎一致,都是為了給終端使用者方便的提供最新資訊。
在伺服器推送技術中,HTTP 串連一直保持著,直到伺服器知道自己已結束髮送資料並發送一個結束訊號,或者用戶端中斷串連。而在用戶端拖曳技術中,並不保持HTTP串連,相反,用戶端被告知合時建立新串連,以及建立串連是擷取什麼資料。
在伺服器推送中,奇妙之處在於“multipart/mixed”格式的MIME,它能夠使一個報文(或HTTP響應)包含許多資料項目、在用戶端拖曳中,奇妙之處在於HTTP回應標頭標(或等效的HTML元素),它能告知用戶端在指定的延時時間後執行何種動作。
伺服器推送通常效率要比用戶端拖曳效率高,因為它不必為後續資料建立新的串連。由於始終保持串連,即使沒有資料轉送時也是這樣,因此伺服器必須願意分配這些TCP/IP連接埠,對於TCP/IP連接埠數有限的伺服器這將是一個嚴重的問題。
用戶端拖曳效率低,因為這必須每次為傳送資料建立新的串連。但是它不必始終保持串連。
在實際情況中,建立HTTP串連通常需要花費相當多的時間,多達一秒甚至更多。因此從效能上考慮,伺服器推送對於終端使用者更有吸引力,特別是對於需要經常更新資訊的情況下。
伺服器推送相對用戶端拖曳的另一點優勢是,伺服器推送相對比較容易控制。例如,伺服器每一次推送時都保持一個串連,但它又隨時可以關閉其中的任何串連,而不需要在伺服器上設定特殊的演算法。而用戶端拖曳在同樣的情況下要麻煩許多,它每次要與伺服器建立串連,伺服器為了處理將用戶端拖曳請求與特定的終端使用者匹配等情況,需要使用相當麻煩的演算法。
如果實現伺服器推送的CGI程式是使用Shell指令碼語言編寫的,有時會存在一些問題。例如,用戶端終端使用者中斷串連,Shell程式通常不能注意到,這將使資源毫無用處的浪費掉,解決這一問題的辦法是用Perl或者C來編寫這類CGI程式,以使使用者中斷串連時能夠結束運行。
如上所述,在伺服器推送中,多個響應中串連始終保持,使伺服器可在任何時間發送更多的資料。一個明顯的好處是伺服器完全能夠控制更新資料的時間和頻率。另外,這種方法效率高,因為始終保持串連。缺點是保持串連狀態會浪費伺服器端的資源。伺服器推送還比較容易中斷。
接下來就大概說說伺服器推送技術
伺服器在響應請求時,HTTP使用MIME報文格式來封裝資料。通常一個HTTP響應只能包含一個資料區塊。但MIME有一種機制可用一個報文(或HTTP響應)表示將多個資料區塊,這種機制就是成為“multipart/mixed”的標準MIME類型。multipart/mixed報文大體格式如下:
Content-type:multipart/mixed;boundary=ThisRandomString
--ThisRandomString
Content-type:text/plain
第一個對象的資料。
--ThisRandomString
Content-type:text/plain
第二個對象的資料。
--ThisRandomString--
上述報文包括兩上資料區塊,二者的類型都是“text/plain”。最後一個“ThisRandomString”後的兩條短線(--)表示報文結束,後面沒有資料。
對於伺服器推送,使用一個“multipart/mixed”類型的變種--multipart/x-mixed-replace。這裡,“x-”表示屬於實驗類型。“replace”表示每一個新資料區塊都會代替前一個資料區塊。也就是說,新資料不是附加到舊資料之後,而是替代它。
下面是實際使用的“multipart/x-mixed-replace”類型:
Content-type:multipart/x-mixed-replace;boundary=ThisRandomString
--ThisRandomString
Content-type:text/plain
第一個對象的資料
--ThisRandomString
Content-type:text/plain
第二個(最後一個)對象的資料。
--ThisRandomString--
使用這一技術的關鍵是,伺服器並不是推送整個“multipart/x-mixed-replace”報文,而是每次發送後資料區塊。
HTTP串連始終保持,因而伺服器可以按自己需要的速度和頻率推送新資料,兩個資料區塊之間瀏覽器僅需在當前視窗等候,使用者甚至可以到其他視窗做別的事情,當伺服器需要發送新資料時,它只是源(ABCIME沒那個字*&^$#)傳輸管道發送資料區塊,用戶端相應的視窗進行自我更新。
在伺服器推送技術中,“multipart/x-mixed-replace”類型的報文由唯一的邊界線組成,這些邊界線分割每個資料區塊。每個資料區塊都有自己的頭標,因而能夠指定對象相關的內容類型和其他資訊。由於“multipart/x-mixed-replace”的特性是每一新資料區塊取代前一資料對象,因而瀏覽器中總是顯示最新的資料對象。
“multipart/x-mixed-replace”報文沒有結尾。也就是說,伺服器可以永遠保持串連,並發送所需的資料。如果使用者不再在瀏覽器視窗中顯示資料流,或者瀏覽器到伺服器間的串連中間(例如使用者按“STOP”按鈕),伺服器的推送才會中斷。這是人們使用伺服器推送的典型方式。
當瀏覽器發現“Content-type”頭標或到達頭標結束處時,瀏覽器視窗中的前一個文檔被清除,並開始顯示下一個文檔。發現下一個報文邊界時,就認為當前資料區塊(文檔)已經結束。
總之,伺服器推送的資料由一組頭標(通常包括“Content-type”)、資料本身和分割符(報文邊界)三部分組成。瀏覽器看到分割符時,它保持狀態不變,直到下一個資料區塊到達。
將以上概念進行用編程方法實現,就可以得到實際的伺服器推送程式。例如,下面的Unix shell程式將使瀏覽器每5秒顯示一次伺服器上的進程列表:
#!/bin/sh
echo "HTTP/1.1 200"
echo "Content-type: multipart/x-mixed-replace;boundary=--ThisRandomString--"
echo ""
echo "--ThisRandomString--"
while true
do
echo "Content-type: text/html"
echo ""
echo "h2Processes on this machine updated every 5 seconds/h2"
echo "time:"
date
echo "p"
echo "plaintext"
ps -el
echo "--ThisRandomString--"
sleep 5
done
注意到,邊界設定在sleep語句之前發送,這能夠確保瀏覽器清除其緩衝區,並顯示所接收到的最新資料。
NCSA HTTPD使用者在內容類型中不能使用空格,包括邊界參數。NCSA HTTPD只能將不帶空白字元的字串作為內容類型。如果在內容類型行中存在空格(冒號後面的空格除外),空格後的任何文本都會被刪除。
下面的樣本是正確的:
Content-type: multipart/x-mixed-replace;boundary=ThisRandomString
而下例則不能正常工作,因為它在中間有空格:
Content-type: multipart/x-mixed-replace; boundary=ThisRandomString
伺服器推送的另一個優點是它可以針對單個內聯圖象進行。包括圖象的文檔可以由伺服器定時或定周期進行更新。而實現這一點非常簡單:只需使IMG元素的SRC屬性指向推送一系列圖象的URL即可。
如果伺服器推送用於單個內聯圖象,文檔中的圖象就會一次次被新推送來的圖象所代替,而文檔本身不需變化(假設文檔沒有進行伺服器推送)。這樣,WEB頁面中有限的動畫就可以為靜態畫面所代替。
用戶端拖曳
用戶端拖曳的一個簡單用法是使文檔按固定周期自動重載。例如,考慮下面的HTML文檔:
<META HTTP-EQUIV="Refresh" CONTENT=1>
<TITLE>Document ONE</TITLE>
<H1>This is Document ONE!</H1>
Here's some text.<P>
如果將它載入支援動態文檔的瀏覽器(Netscape 1.1以上,Internet Explorer和Mosaic也支援用戶端拖曳),它將每隔一秒將自己重載一次。
由於META元素實際是在HTML文檔中類比HTTP回應標頭標,所以它能夠告知瀏覽器將自身資訊當作HTTP響應使用。上例中的META標記相當於:
Refresh:1
這樣,實際上就是HTTP頭標告知瀏覽器每一秒更新一次文檔。如果需要延時是12秒,那麼就是這樣的指令:
<META HTTP-RQUIV="Refresh" CONTENT=12>
那麼它等效於:
Refresh:12
關於用戶端的拖曳我也懶的繼續寫下去,關於怎麼使用戶端自動申請其他URL的資料話,請使用如下:
<META HTTP-EQUIV="Refresh" CONTENT="12;URL=http://icools.yeah.net/">
注意的是,此處的URL不能使用相對路徑,必須全部指定。
其中時間間隔可以設定為0,這樣瀏覽器在當前文檔顯示完畢後,以最快的速度載入新的資料!