2014-02-14 76 views
0

在我的網站上,我構建了一個支持多個房間的聊天室。當用戶加入房間時,會話將被放入數據庫,以便如果他們嘗試在另一個瀏覽器窗口中再次加入房間,則會被鎖定。在卸載javascript之前關閉服務器端聊天連接

它的工作原理是這樣

1. Join the chatroom page 
2. Connect to chatroom #main 
If the user has a session in the database for #main 
--- Block user from joining 
else 
--- Load chatroom 

當聊天室被關閉客戶端或使用/ quit命令用戶終止有聯繫,他們的所有會話被刪除,這工作得很好。

然而
有一種可能性,即用戶將只關閉瀏覽器窗口,而不是終止其連接。問題在於他們的會話將保留在數據庫中,這意味着當他們嘗試連接到房間時,他們被阻止。

我使用這個代碼onbeforeunload嘗試和防止

function disconnect() { 
     $.ajax({ 
      url: "/remove-chat-sessions.php?global", 
      async: false 
     }); 
}; 

這也被稱爲當用戶鍵入/ quit命令

問題
有問題的功能這是當我重新加載頁面時,10次中有5次會話沒有被帶出數據庫,就好像ajax請求失敗或頁面在它完成之前被重新加載一樣。這意味着當我回到聊天室時,數據庫仍然認爲我已連接,並阻止我進入聊天室

有沒有更好的方法來確保此AJAX調用將加載,如果沒有,是有沒有比在線數據庫中存儲用戶會話更好的選擇?

編輯:
用戶從加盟客房多次受阻的原因是因爲你發佈的消息似乎沒有你有新郵件聊天室更新時。當他們發佈時,它們會附加到聊天室框中。這意味着如果用戶可能在多個窗口中處於同一個聊天室中,他們將無法看到他們在所有窗口中發佈的評論。

+0

或許不是阻止他們加入新會話,而應該使舊會話無效並使用新的會話。 –

+0

@JonathanKuhn,他們被阻止的原因是因爲你發佈的消息沒有出現在聊天室中。他們出現在你發佈時。這意味着如果用戶可能在多個窗口中處於同一個聊天室中,他們將無法看到他們在所有窗口中發佈的評論。 –

+0

因此,讓我們說你有一個輪詢,每隔幾秒檢查一次新消息。當它進行輪詢時,讓它檢查表中的會話是否與請求的會話匹配。如果它們不匹配,則發回消息「由於您已登錄到另一個窗口而斷開連接」並停止輪詢。然後,只有在他們加入/離開房間時纔會在表中設置會話,而不是輪詢。 –

回答

0

在這種情況下,您可以添加某種輪詢。基本上,你每隔X次請求一個JavaScript頁面。該頁面將用戶會話添加到數據庫。然後有一個腳本執行每Y時間,其中Y> X,清理舊會話。

被稱爲每隔X時間

... 
// DB call (do as you like) 
$All = fetch_all_recent(); 
foreach ($All as $Session) 
    { 
    if ($Session['time'] < time() - $y) 
    { 
    delete_session($Session['id']); 
    } 
    } 

腳本JavaScript是要求每X時間

... 
delete_old_session($User->id); 
add_user_session($User->id, $Chat->id, time()); 

這種方法的主要缺點是在請求增量腳本,一些Apache是不太習慣(對於大的請求數)。這有兩個非排他性的替代方案,其中涉及對服務器的訪問,分別是:

  1. 使用nginx server。我沒有這方面的經驗,但我讀過它支持比Apache更多的連接。

  2. 使用一些現代形式的持續連接,如socket.io。但是,它使用node.js,這可能是好的或壞的,具體取決於您的業務。

+0

以我的經驗,nginx比apache更好地處理靜態頁面/內容,但是apache更好地處理動態內容,比如php。無論哪種方式,這只是一個意見,並沒有真正需要回答這個問題。 –

+0

這幫助我去了我需要做的,謝謝。 –