最近找輪詢的資料,看到不錯的文章就收藏進來javascript
沒辦法硬着頭皮查找長輪詢的資料吧~ 文字較多,耐心看看但願對大家有幫助php
傳送門
:Web 通訊 之 長鏈接、長輪詢(long polling)html
看了不少,以爲以上文章是最好的.裏面說到輪詢會出現的狀況(文字功底很差只能拿來主意):前端
輪詢的創建
創建輪詢的過程很簡單,瀏覽器發起請求後進入循環等待狀態,此時因爲服務器還未作出應答,因此HTTP也一直處於鏈接狀態中。java
數據的推送
在循環過程當中,服務器程序對數據變更進行監控,如發現更新,將該信息輸出給瀏覽器,隨即斷開鏈接,完成應答過程,實現「服務器推」。jquery
輪詢的終止,輪詢可能在如下3種狀況時終止:ajax
輪詢的重建
瀏覽器收到回覆並進行相應處理後,應立刻從新發起請求,開始一個新的輪詢週期。json
首先, 就是PHP後端的問題, 在輪詢的時候後端會用while(true)的形式, 來hold住這個Ajax請求, 讓他遲遲不能得到數據, 一旦獲取數據前端Ajax立馬就會作出飛通常的反應(網絡好的時候確實飛呀飛~).後端
可是別太樂觀, 一旦咱們的前端終止了請求, 那麼服務端PHP就無限的循環下去, 他不會終止了! 伴隨着ignore_user_abort(true)
和set_limit_time(0)
這個程序會很歡快的跑下去, 並且你會發現你的其餘業務都會由於這樣而中止!瀏覽器
你媽媽的吻~
查詢了一些資料後, 是由於session處於被鎖的狀態.因此致使了其餘頁面也跟着不能正常了.解決方案: session_write_close()
, 頁面總算正常了.
只不過呢? 程序仍是歡快的在後臺放羊般的執行着, 並且你還不知道, 知道筆記本發熱你纔會覺察.
這個時候我就在想, 有沒有一個PHP函數可讓PHP知道前端已經斷開了, 讓死循環終止吧~
結果一Google~ 真有!!! 噹噹噹當~~
connection_aborted() //就是他! 返回值: 未斷開爲false 斷開爲true
有了這個咱們就能夠在客戶端斷開\關閉瀏覽器\Ajax超時執行的時候自動終止程序了.說了這麼多, 感受仍是來看看代碼吧.光說不練假把式~
這個代碼只是一個測試例子, 測試效果是否被實現, 讀者能夠自行修改.
首先, 是前端HTML代碼:
<html lang="en"> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="./jquery1.4.2.js"></script> <script type="text/javascript"> $(function () { var MsgBox = { MsgObj: $('#msg'), showMsg: function (msg) { MsgBox.MsgObj.html(msg); } } //輪詢 var Comet = { Init: function () { $('#btn').unbind(); $('#btn').bind('click', Comet.Poll); }, //輪詢 Poll: function () { //爲了打日誌寫的東西,隨機生成的 var id = parseInt(Math.random() * 1000); MsgBox.showMsg(''); $.ajax({ url: './test.php', //訪問地址 type: 'post', //post方式提交 data: {id: id}, //傳入ajax數據 dataType: 'json', //返回格式 timeout: 10000, //超時設置三十秒 success: Comet.Success, //成功時的返回 error: Comet.Failed //失敗的時候 }); }, //成功獲取數據時 Success: function (data) { if (data.status == 1) { MsgBox.showMsg(data.info); } }, //沒有獲取數據 Failed: function (XMLHttpRequest, textStatus, errorThrown) { //超時從新鏈接 if (textStatus == 'timeout') { Comet.Poll(); } else { Comet.Poll(); } } }; Comet.Init(); }); </script> </head> <body> <div id="msg"></div> <input type="button" value="開始" id="btn"> </body> </html>
這部分代碼只是讓前端在點擊開始後,不斷的Ajax提交訪問請求, 添加了超時時間, 讓Ajax能夠在超時時候中斷鏈接, 而後經過錯誤處理從新啓動, 用遞歸來作循環吧(個人理解), 這個沒有什麼難度. 其實技術說穿了都那樣白菜價.
而後是,Ajax請求中的test.php:
<?php //讓腳本無限制執行下去 set_time_limit(0); ignore_user_abort(true); session_write_close(); $i=1; while(true){ //未斷開鏈接就處理嘛 if(!connection_aborted()){ sleep(1); if($i >= 50) { echo json_encode(array('status'=>1, 'info'=>'lalalala')); break; } $i++; } } //斷了鏈接,我就記錄下,爲了調試效果是否成功! 實際中看狀況使用 if(!connection_aborted()){ echo json_encode(array('status'=>1, 'info'=>'中止了')); file_put_contents('stop.txt',"stop:".$_POST['id'].'-----'.date('Y-m-d H:i:s')."\n", FILE_APPEND); exit(); }
原連接:http://blog.csdn.net/xiaobaig0407/article/details/48676563
舒適提示:
HTML的代碼裏面jQuery庫請自行添加, 我就不提供了.
在你點擊了前端的"開始"後, 請注意咱們的Chrome中的時間線, 我設置了十秒超時, 因此你每隔10s就能夠看到一個新的Ajax請求去訪問後端PHP, 然後端有沒有終止, 你只須要在Linux下的用tail -f stop.txt
這個日誌文件就能夠看到實時的日誌變化.