背景:一直都覺得資訊推送是個很實用的功能。以前想到的最初實現方案是:用ajax隔段時間請求一次後台,由後台取出最新訊息後作為傳回值給ajax回調展示。今天看到了一個不太一樣的解決方案:在php端通過while判斷資訊有沒有發生變更,有則返回給前台展示,展示完後繼續發送ajax請求給php後台監視資訊;沒有的時候,php端while就保持迴圈監視資訊狀態,這樣請求沒有結束,ajax的狀態不會完成,也就不用重新發送請求了。
兩種方案後來分析了下,大致結果如下
第一種隔段時間發送一次的,因為請求頻率的問題,必然導致請求次數多。但是這種的每個請求都會很快放開,不需要監視資訊變化,只關注請求進來時的資訊就可以了。
第二種由php端通過while輪詢監視資訊是否變化,有變化的時候結束請求,返回給ajax顯示,再發送下一次的監視請求;沒變化則while迴圈一直監視。這種方案的話,會大大的減少請求次數問題,但是會導致每個使用者對應一個伺服器端php監視業務。另外php是沒有多線程概念的,用apache的時候有個可以限制最大訪問量的設定項MaxRanges。這些問題考慮進去的話會導致一些伺服器端同時訪問量超標的問題。
第三種聽同事談到的strophe.js是用於解決web im的已封裝好外掛程式。(應用的話之後在寫)
備忘:以上兩種方案,具體應用的話,可能還是需要看情境取捨吧
第一種方案的代碼,就略了(主要是while,setTimeout,ajax,遞迴調用之類的)。和下面第二種應用的代碼很多會相同的。
上第二種代碼:
<?php// 佈建要求已耗用時間不限制,解決因為超過伺服器已耗用時間而結束請求ini_set("max_execution_time", "0");$filename = dirname(__FILE__).'/data.txt';$msg = isset($_GET['msg']) ? $_GET['msg'] : '';// 判斷頁面提交過來的修改內容是否為空白,不為空白則將內容寫入檔案,並中斷流程if ($msg != ''){ file_put_contents($filename,$msg); exit;}/* 擷取檔案上次修改時間戳記 和 當前擷取到的最近一次檔案修改時間戳記 * 檔案上次修改時間戳記 初始 預設值為0 * 最近一次檔案修改時間戳記 通過 函數 filemtime()擷取 */$lastmodif = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;clearstatcache(); // 清除檔案狀態緩衝$currentmodif = filemtime($filename);/* 如果當前返回的檔案修改unix時間戳記小於或等於上次的修改時間, * 表明檔案沒有更新不需要推送訊息 * 如果當前返回的檔案修改unix時間戳記大於上次的修改時間 * 表明檔案有更新需要輸出修改的內容作為推送訊息 */while ($currentmodif <= $lastmodif){ usleep(10000); // 休眠10ms釋放cpu的佔用 clearstatcache(); // 清除檔案狀態緩衝 $currentmodif = filemtime($filename);}// 推送資訊處理(需要推送說明檔案有更改,推送資訊包含本次修改時間、內容)$response = array();$response['msg'] = file_get_contents($filename);$response['timestamp'] = $currentmodif;echo json_encode($response);flush();?>html頁面代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Comet demo</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript" src="./jquery-1.8.2.min.js"></script><script type="text/javascript" src="./json2.js"></script><script> var timestamp = 0; var url = 'backend.php'; var error = false; // 通過ajax建立和php端處理函數的串連(通過遞迴調用建立長時間的串連) function connect(){ $.ajax({ data : {'timestamp' : timestamp}, url : url, type : 'get', timeout : 0, success : function(response){ var data = JSON.parse(response); error = false; timestamp = data.timestamp; if (data.msg != undefined && data.msg != "") { $("#content").append("<div>" + data.msg + "</div>"); } }, error : function(){ error = true; setTimeout(function(){ connect();}, 5000); }, complete : function(){ if (error) // 請求有錯誤時,延遲5s再串連 setTimeout(function(){connect();}, 5000); else connect(); } }) } // 發送資訊 function send(msg){ $.ajax({ data : {'msg' : msg}, type : 'get', url : url }) } // 建立長時間的串連 $(document).ready(function(){ connect(); })</script></head><body> <div id="content"></div> <form action="" method="get" onsubmit="send($('#word').val());$('#word').val('');return false;"> <input type="text" name="word" id="word" value="" /> <input type="submit" name="submit" value="Send" /> </form> </body></html>需要匯入js資源:jquery,json2.js