2011-01-27 381 views
93

我正在玩弄HTML5 WebSockets。我想知道,我如何優雅地關閉連接?比如,如果用戶刷新頁面或關閉瀏覽器會發生什麼?正確關閉WebSocket(HTML5,Javascript)

當用戶只刷新頁面而不調用websocket.close() - 當它們在刷新後返回時它會碰到websocket.onclose事件時會出現奇怪的行爲。

回答

70

按照protocol spec V76(這是該瀏覽器當前支持實施的版本) :

爲了乾淨地關閉連接,一幀只包含一個0xFF字節 後跟一個0x00字節從一個對等方發送,要求其他對等方關閉連接。

如果您正在編寫服務器,則應確保在服務器關閉客戶端連接時發送關閉幀。正常的TCP套接字關閉方法有時可能會很慢,並導致應用程序認爲連接仍然打開,即使它不是。

當你關閉或重新加載頁面時,瀏覽器應該爲你做這些事情。但是,你可以確保一個緊密框架做捕獲beforeunload事件發送:

window.onbeforeunload = function() { 
    websocket.onclose = function() {}; // disable onclose handler first 
    websocket.close() 
}; 

我不知道如何可以刷新頁面後會得到onClose事件會。一旦頁面重新加載,websocket對象(使用onclose處理程序)將不再存在。如果您在頁面加載時立即嘗試在頁面上建立WebSocket連接,那麼您可能會遇到服務器在舊連接斷開後很快拒絕新連接的問題(或者瀏覽器尚未準備就緒在你嘗試連接的地方建立連接),並且你得到了一個新的websocket對象的onclose事件。

+1

這可能是在Firefox中,連接似乎流連進入下一個頁面加載。我找不到參考,但我認爲可能有一個關於此的錯誤。另一種可能性是`onclose`事件被意外觸發,或者可能是故意的,因爲用戶導航/頁面被重新加載。我[張貼的問題(http://stackoverflow.com/questions/10965720/should-websocket-onclose-be-triggered-by-user-navigation-or-refresh),詢問預期的行爲應該是什麼,這瀏覽器是否正確以及如何實現自動重新連接。 – leggetter 2012-06-10 01:10:28

+3

考慮[這些問題](http://stackoverflow.com/questions/14645011/window-onbeforeunload-and-window-onunload-is-not-working-in-firefox-safari-o)用`onbeforeunload`事件 – artkoenig 2015-01-16 21:06:05

31

事情就是今天使用的WebSocket有兩個主要協議版本。使用[0x00][message][0xFF]協議的舊版本,然後是使用Hybi格式化數據包的新版本。

Opera和iPod/iPad/iPhone使用舊協議版本,所以在WebSockets服務器中實現向後兼容性非常重要。使用這些瀏覽器使用舊協議時,我發現刷新頁面或從頁面導航或關閉瀏覽器都會導致瀏覽器自動關閉連接。大!!

但是,對於使用新協議版本的瀏覽器(例如Firefox,Chrome和最終IE10),只有關閉瀏覽器纔會導致瀏覽器自動關閉連接。也就是說,如果刷新頁面或離開頁面,瀏覽器不會自動關閉連接。然而,瀏覽器的功能是發送一個hybi數據包到第一個字節(proto ident)爲0x88(更好的稱爲關閉數據幀)的服務器。一旦服務器收到這個數據包,它可以強制關閉連接本身,如果你願意的話。

+3

一個在服務器端如何管理這個hybi包的實際例子? – albanx 2013-01-09 07:03:10

2

正如所述,theoobe,有些瀏覽器不會自動關閉websockets。不要試圖處理客戶端的任何「關閉瀏覽器窗口」事件。目前還沒有可靠的方法來做到這一點,如果考慮支持主要的桌面移動瀏覽器(例如onbeforeunload不會在移動Safari瀏覽器工作)。我在處理服務器端的這個問題方面有很好的經驗。例如。如果你使用Java EE,看看javax.websocket.Endpoint,根據不同的瀏覽器中使用的OnClose方法或OnError方法上如果關閉/重新加載瀏覽器窗口將被調用。