2013-10-05 108 views
-1

在許多地方,我在網上看到過許多問題,但是,在大約30個論壇和其中沒有任何一個有我需要的解決方案的情況下,包括計算器。如果有人能幫我找到一個可靠的解決方案,將不勝感激,所以提前致謝!在瀏覽器中關閉數據庫用戶關閉PHP/MySQL

我將盡可能詳細地解釋我的網站和情況,以幫助任何想幫助解答我的問題的人。這是我的情況:

我有一個網站,我使用PHP和MySQL。我的網站是一個「私人」組織網站。爲了讓人們能夠訪問該網站,我發送了我們組織的新成員並邀請了代碼。然後用戶訪問該網站,並且index.php文件僅包含用於登錄的表單以及到註冊頁面的鏈接。新會員點擊「在此註冊」鏈接開始註冊。第一個註冊頁面要求提供用戶的姓氏和邀請代碼,這些代碼是針對數據庫進行檢查的,以確保該人員在列表中並且尚未註冊。如果他們通過了支票,他們將進入下一頁,在那裏他們輸入所需的信息(用戶名&密碼,電子郵件地址等)以及一些可選信息(電話,生物等)。如果用戶創建了有效的用戶名和密碼並填寫了所有必填字段,則其信息將存儲在數據庫中。所有密碼都被妥善安全地進行了醃製和散列處理,因此這裏沒有問題,並且整個註冊過程都按照原樣進行。註冊後,用戶將被帶回index.php,他們現在可以使用剛纔創建的用戶名和密碼登錄。這也適用;當用戶登錄時,將根據數據庫檢查其用戶名和密碼,如果成功,則用戶登錄。當用戶登錄時,數據庫中的ONLINE值將從False設置爲True。用戶現在已經登錄並可以按照預期使用該網站。在我的網站上,有一列列出當前在線的用戶(基於數據庫的ONLINE值)。當用戶點擊站點每個頁面上的「註銷」按鈕時,將運行logout.php腳本,結束會話並將ONLINE值設置爲False。這一切都可以正常工作,但是,當用戶關閉瀏覽器而未先註銷時,問題就來了。這是我在互聯網上看到許多不同「解決方案」的地方。我將解釋他們爲什麼不能工作,爲什麼我需要更好的解決方案。

我看到的答案最經常涉及某種會話超時或銷燬會話,這是無關緊要的,因爲會話已經完成,事實上,當用戶關閉瀏覽器時結束,但這對於告訴其他用戶該人目前是否在線。會話結束時,數據庫不會更新,這會導致問題,因爲用戶只能從單個實例登錄。如果用戶嘗試登錄時,他們的ONLINE值已設置爲TRUE,則不允許他們登錄。

我也看到了使用「Last Seen」值而不是在線值的建議,以及如果用戶在過去的x分鐘內沒有任何活動,請將用戶註銷。但這不起作用,原因有兩個。 1)該腳本仍然需要運行才能工作,這意味着另一個用戶必須登錄才能正常工作。這基本上意味着,如果使用這種方法,如果用戶關閉瀏覽器或者他們的連接鬆動,他們將無法重新登錄,直到其他用戶登錄。由於我的組織是一個小型的本地組織,因此它是的,可能有很多次沒有用戶在線。另外,即使其他用戶登錄,連接丟失的用戶仍然無法重新登錄,直到x分鐘數過去,因此如果用戶意外關閉瀏覽器並想立即重新登錄,他們根本無法做到。

我遇到的一個不太常見的解決方案涉及到使用onBeforeUnload JavaScript函數,但那些肯定不會工作,因爲這些會觸發任何時候用戶點擊鏈接或在「後退」和「前進「 鈕釦。另外,如果用戶在其瀏覽器中禁用了JavaScript,則這完全不起作用。

我所看到的最後一件事涉及while循環和connection_aborted函數,這是唯一一個看起來可以工作的函數,但我還沒有看到如何工作的非常明確的描述,並花費了幾個月試驗它,我還沒有想出一個可靠的解決方案。

在很多論壇中,我看到有人說「這不可能」,但考慮到有些網站會以某種方式做到這一點,情況並非如此。我已經在幾個網站上對此進行了測試和實驗。在擁有諸如Facebook或任何論壇網站的用戶的網站上,存在「在線」用戶的列表,並且在用戶關閉他們的瀏覽器的情況下,他們的名字將不再出現在列表上,因此,即使只能通過一些不明確的方法來實現。所以,如果有人知道一個解決方案,我將非常感謝,如果你能分享你的這個問題的一些智慧!

+1

最好的辦法是簡單地加入一個不活動的超時時間。如果在過去10或15分鐘(或其他時間)內沒有任何活動,請將該人員關閉。我不贊成你的觀點,認爲這是行不通的;正在運行的Web應用程序是正在運行的Web應用程序 –

+0

可能牽強附會,或者過多的努力來實現,但你可以檢查出socket.io,它通過HTTP向客戶端提供了一種非常可靠的傳輸方法,並且可以輕鬆檢測套接字斷開連接。 – mobius

+0

您可以設計您的客戶端瀏覽器代碼,以便在用戶離開頁面時發送結束用戶會話的消息。但是,儘管你的直覺相反,你*不能*保證這樣的消息將始終由網絡應用客戶端代碼發送。如果用戶在窗戶打開時從筆記本電腦中拉出電池,該怎麼辦?您需要超時策略作爲會話取消的備份。 –

回答

0

嘗試在javascript中創建心跳機制。 這種方法將開始發送一個Ajax調用您的webmethod及時使用。

setInterval(function(){ 
sendPulse(); 
},30000); 


sendPulse(){ 

var varUserID = userID;//any unique user identifier that can be found on server side 
$.ajax({ 

    url: "Default.php/updateUserStatus", 
    UserID: varUserID, 
    type: "POST", 
    dataType: "json", 
    contentType: "application/json; charset=utf-8", 
    success: function (mydata) { 

     //alert("pulse sent"); 
    } 
    }); 
    } 

在服務器端,您必須具有名稱和區分大小寫參數的方法。應該是靜態的並且標記爲webmethod。在這種方法中保存用戶的當前時間。你應該有一種機制來知道用戶有什麼舊脈搏,當用戶嘗試做某事或執行任何操作時,請檢查這些機制。我已經實施了這種方法並且工作得很好。

0

這就是答案:客戶端和服務器之間的持續連接。爲此,您需要一個TCP連接,比如現在的websockets,或者舊的雙工連接。從這裏開始,當有人連接或斷開連接時,TCP負責注意到你。你需要做的是一個websocket服務器(例如),它只是傳遞連接(從數組中push和pop),還有一種迴應「get_users_online」消息的方式。您可以通過websocket服務器訪問您的用戶會話(只讀),然後查看用戶是否已登錄(並且以這種方式,您可以在會話中存儲他的暱稱,從websocket服務器進一步訪問),看看他是否是admin(session-> is_admin)。

很簡單,我會說。

這是我一直在使用的圖書館:http://socketo.me/。它使用庫來解碼symfony2會話,但對於簡單的應用程序,您不需要解碼(symfony2應用程序會對會話進行編碼,因此websocket服務器必須解碼它們)。

備註:會話必須存儲在外部(不在文件系統/ tmp中),如ORM或NoSql。

無論哪種方式,請原諒我,但我必須說,看到的「最後一次」是超級奧奇。大多數網站都依賴於此。你明白了一些錯誤,你不需要有一個活着的服務器來檢查「最後一次」,當你請求/admin.php?users_online=1時,你在「Last seen> NOW()」中查詢5分鐘「(不會這樣寫),所以你甚至可以擺脫」在線「」離線「字段。

我建議使用websocket方法,它很有趣。 :)

祝你好運!

+0

這對我來說看起來很不錯。我會試試這個。謝謝。 – tboneblaze