2009-11-23 105 views
2

我是新來這個網站,所以我真的希望我會提供所有關於我的問題的必要信息。Ajax長輪詢(彗星)+ PHP上lighttpd v1.4.22多個實例問題

我一直在嘗試使用長輪詢來創建「新郵件到達通知」。目前,我正在通過我網站中每個頁面的window.onLoad事件啓動輪詢請求。

在服務器端我有無限循環:

while(1){ 
if(NewMessageArrived($current_user))break; 
sleep(10); 
} 
echo $newMessageCount; 

在客戶端我有以下的(簡化的)AJAX功能:

poll_new_messages(){ 
xmlhttp=GetXmlHttpObject(); 
//... 
xmlhttp.onreadystatechange=got_new_message_count; 
//... 
xmlhttp.send(); 
} 

got_new_message_count(){ 
if (xmlhttp.readyState==4){ 
    updateMessageCount(xmlhttp.responseText); 
    //... 
    poll_new_messages(); 
} 
} 

的問題是,在每個頁面載入,上面的循環再次開始。結果是多個無限循環爲每個用戶,最終使我的服務器掛起。

* NewMessageArived()函數向MySQL DB查詢新的未讀消息。

*在php腳本的開頭,我運行start_session()以獲得$current_user的值。

我目前是本網站的唯一用戶,因此我很容易通過將time()寫入此循環中的文件來調試此行爲。我所看到的是文件在10秒內被寫入的次數比一次多,但是隻有當我一頁一頁地進行時纔會啓動。

如果有任何其他信息可能有幫助,請讓我知道。

謝謝。

回答

0

您可能會嘗試定期檢查connection_aborted()。請注意,connection_aborted()可能沒有提及事實:連接實際上已被中止,直到你寫了一些輸出並完成了flush()

事實上,只是定期產生一些輸出可能足以讓php注意到連接本身並關閉,並自動殺死腳本。

+0

謝謝您的回答。每次我回復一些數據時,這個解決方案不會觸發ajax響應函數嗎?使此解決方案成爲常規輪詢而不是長輪詢。 – fibonacci 2009-11-23 21:20:00

1

長輪詢請求在30秒後超時似乎很常見。所以在你的while循環中,你可以在30秒後回顯'CLOSE'。

while(!$new_message && $timer < 30){ 
    $new_message = NewMessageArrived($current_user); 
    if(!$new_message) { 
     sleep(10); 
     $timer += 10; 
    } 
} 
if($newMessageCount) { 
    echo $newMessageCount; 
} else { 
    echo 'CLOSE'; 
} 

在JavaScript中,你可以聽的關閉。

function poll_new_messages(){ 
    xmlhttp=GetXmlHttpObject(); 
    //... 
    xmlhttp.onreadystatechange=got_new_message_count; 
    //... 
    xmlhttp.send(); 
} 

function got_new_message_count(){ 
    if (xmlhttp.readyState==4){ 
     if(xmlhttp.responseText != 'CLOSE') { 
      updateMessageCount(xmlhttp.responseText); 
     } 
     //... 
     poll_new_messages(); 
    } 
} 

現在,無論如何,PHP都會在30秒內返回響應。如果您在頁面上使用停留,並且您收到CLOSE,則只需不更新頁面上的計數,然後重新提問。

如果用戶移動到新頁面,您的PHP實例將在30秒內停止循環,並返回響應。雖然在新頁面上,但關心該連接的XHR不再存在,所以它不會啓動另一個循環。

+0

謝謝你的回答。我的ajax函數poll_new_messages()有一個響應處理程序got_new_message_count()函數。響應處理程序在觸發時調用poll_new_messages()。 因此,在這兩種情況下,我將最終得到相同數量的無限循環或沒有響應處理函數(如果在CLOSE上,我將不再調用poll_new_messages)。 – fibonacci 2009-11-23 21:27:54

+0

在Javascript中,你可以檢查「CLOSE」,如果是的話,重新調查。否則,顯示計數。如果用戶更改頁面,當循環超時時,它不會從您的處理程序重新啓動,因爲處理程序不再偵聽(從該頁面)。 – seanmonstar 2009-11-24 00:05:39

+0

當另一個$ newMessageCount再次到達時,會發生什麼情況,此事件沒有處理程序?您提出的解決方案只會通知用戶一次(如果用戶不會更改頁面並再次開始長輪詢)。 – fibonacci 2009-11-24 06:43:13

1

我想我找到了解決我的問題。如果有人能夠告訴我,如果這是在COMET中使用的技術,以及這種解決方案的可擴展性如何,我將不勝感激。

我用這樣的基於用戶的信號:

$sem_id = sem_get($current_user); 
sem_acquire($sem_id); 
while(1){ 
if(NewMessageArrived($current_user))break; 
sleep(10); 
} 
sem_release($sem_id); 
echo $newMessageCount;