查閱詞典Comet中文是“彗星”的意思,起初我見到這個單詞的時候,我就猜想優美名字背后到底是什么呢?他是一種WEB服務器推的應用技術(Server Push)。Server Push就如同它自己的名字一樣,將更多華麗的web體驗“推”進了我們的視野。有 一些觀點 將Comet比作是 Ajax 的接班人,這個觀點 我無法茍同,我認為Ajax 與Comet 并不存在取代關系。 從實質上講 Comet 還是Ajax的應用。
要講清楚Comet是什么的問題?我不妨將話題扯遠點,我們先了解下web開發的歷史。
大家一定還記得從前,我們在論壇注冊賬號,一點了提交按鈕,頁面就一片空白(服務器在刷新頁面,處理提交數據),ie的狀態圖就不停的轉,一個提交按鈕一點,頁面就再也不能進行其他操作了(因為這里的數據請求和界面操作是同步的)。我們就傻等著服務器處理完數據后返回,以前網速也慢,服務器性能也差。那么這個等待時間就會挑戰大家的容忍極限。這個就是Ajax誕生要解決的問題。
其實在Ajax這個名字沒有出現的時候,‘Ajax’的應用就已經存在了。那時前輩們就已經在WEB方面為追求更完美的用戶體驗,為追求異步通信,為追求局部刷新摸索出了一些可重用的方式方法。大致方法有2種:
一種是頁面中放入一個隱藏的frame 頁面,這個頁面有一個表單form對象。而數據的提交,就交給這個 frame 頁面。就算是刷新也是這個頁面刷新,而這個頁面由于是隱藏的或者高度和寬度設置為0的,所以刷新時候用戶感覺不到。那么當數據返回的時候也就能夠達到局部刷新的效果。而且用戶操作的頁面不用被卡住,這樣也達到異步通信的效果了。這種是比較古老和麻煩的方法。
另外一種和當今的Ajax就很類似了。開發人員開發自己的ActiveX 控件,這個控件的功能基本和現在Ajax 差不多,其實Ajax 大家也可以看成是一個ActiveX 控件,只是各大瀏覽器都實現了這個ActiveX 控件。所以現在我們開發Ajax應用,不用自己開發這個ActiveX 控件。
Ajax實現了對XMLHTTP對象的封裝,這個對象有一系列接口,比較重要的是發送異步數據的接口。
2.那Comet是在什么歷史背景下誕生的呢?
當服務器端數據發生變化時,客戶端如何即時得到通知呢?這個就是Comet誕生的背景。
1.
傳統方法定時刷新,就是隔一個時間段瀏覽器刷新一次。(沒有用戶受得了這種方法,服務器也害怕遇到這種事情)
2.
長輪詢(long-polling)
Ajax隔一段時間就去服務器查詢是否有更新,但是多長時間去查詢成了問題。因為性能和即時性造成了嚴重的反比關系。
3.在前面兩種方法被否定后,想到了服務器推送至客戶端這種模式,但是web開發客戶端是一個瀏覽器(并不是我們自己控制的GUI客戶端)。所以Comet登場,簡單說還是利用Ajax與服務器建立http長連接查詢是否有數據更新,服務器收到一個連接如果沒有數據更新就阻塞這個連接不要返回給客戶端,直到有新數據再返回給客戶端。Web客戶端,發起的連接一旦被返回,或者超時就再次建立http長連接。這樣就能保證數據的即時更新,以及盡量減少服務器的計算工作。 2. Comet的一些應用
目前Comet主要應用在一些股票web客戶端,以及一些基于web的即時聊天系統中。
比較成熟的框架有Dojo ,Dwr 等一些Ajax框架中實現了該功能。
3.
Comet
優、
缺點
3.1 缺點
長期占用連接,喪失了無狀態高并發的特點。
server push不會是一個沒有副作用的解決方案,是否適合還要仔細權衡。
3.2 優點
Ø
實時性好(消息延時小)
Ø
性能好(能支持大量用戶)
4.其他服務器推技術
Comet 只是眾多服務器推技術中的一種,目前市面上還有許多其他流行服務器推技術。
4.1
Flash XMLSocket
這種方案實現的基礎是:
1.
Flash 提供了 XMLSocket 類。
2.
JavaScript 和 Flash 的緊密結合:在 JavaScript 可以直接調用 Flash 程序提供的接口。
但此方案的缺點在于:
1.
因為 XMLSocket 沒有 HTTP 隧道功能,XMLSocket 類不能自動穿過防火墻;
2.
因為是使用套接口,需要設置一個通信端口,防火墻、代理服務器也可能對非 HTTP 通道端口進行限制;
不過這種方案在一些網絡聊天室,網絡互動游戲中已得到廣泛使
用
。
4.2 Java Applet 套接口
在客戶端使用 Java Applet,通過
java.net.Socket
或
java.net.DatagramSocket
或
java.net.MulticastSocket
建立與服務器端的套接口連接,從而實現“服務器推”。
這種方案最大的不足在于 Java applet
需要客戶端安裝JAVA虛擬機
。
5. 總結
Comet
不存在什么新技術,沒有什么神秘可言
。
瓶頸主要集中在web server這一塊,一般成熟的
Comet
商業應用都會有一套它自己專用的web server,比如lightstreamer就是這樣!
實例解析:
服務端:
$filename = dirname(__FILE__).'/data.txt';
$msg = isset($_GET['msg']) ? $_GET['msg'] : '';
if ($msg != '')
{
//寫入內容至文件
file_put_contents($filename,$msg);
die();
}
set_time_limit(0);
$lastmodif = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
//取得文件最后修改時間
$currentmodif = filemtime($filename);
while ($currentmodif <= $lastmodif)
{
//有釋放CPU占用率的作用
usleep(10000);
//清除文件緩存信息
clearstatcache();
$currentmodif = filemtime($filename);
}
// return a json array
$response = array();
$response['msg'] = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);
ob_flush();
flush();
?>
客戶端:
{
if (!WebApp._noerror_)
{
setTimeout(WebApp.WebMain, 5000);
}else
{
setTimeout(WebApp.WebMain, 10);
}
WebApp._noerror_ = false;
}
可以看到不管成功失敗都將開始一次新的ajax請求。也就是保持了連接。
使用方法:
1.需要php服務器;
2.開兩個不同瀏覽器即可掩飾效果。
這只是一個介紹原理型demo,請勿商業使用。
DEMO下載