WebSocket'i doğru şekilde kapatma (HTML5, Javascript)


127

HTML5 WebSockets ile oynuyorum. Merak ediyordum, bağlantıyı nasıl zarif bir şekilde kapatabilirim? Örneğin, kullanıcı sayfayı yenilerse veya tarayıcıyı kapatırsa ne olur?

Bir kullanıcı aramadan sayfayı yenilediğinde tuhaf bir davranış vardır websocket.close()- yenilemeden sonra geri döndüğünde, websocket.oncloseetkinliğe çarpacaktır .

Yanıtlar:


111

Göre protokol Spec (akım desteği ile tarayıcı uygulamanızı versiyonudur) v76:

Bağlantıyı temiz bir şekilde kapatmak için, yalnızca bir 0xFF bayt ve ardından bir 0x00 bayttan oluşan bir çerçeve, diğer eşin bağlantıyı kapatmasını istemek için bir eşten gönderilir.

Bir sunucu yazıyorsanız, sunucu bir istemci bağlantısını kapattığında yakın bir çerçeve gönderdiğinizden emin olmalısınız. Normal TCP soket kapatma yöntemi bazen yavaş olabilir ve uygulamaların bağlantı olmadığında bile bağlantının hala açık olduğunu düşünmesine neden olabilir.

Tarayıcı, sayfayı kapattığınızda veya yeniden yüklediğinizde bunu sizin için gerçekten yapmalıdır. Ancak, beforeunload olayını yakalayarak yakın bir çerçevenin gönderildiğinden emin olabilirsiniz:

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

Sayfa yenilendikten sonra onclose olayını nasıl elde edeceğinizden emin değilim. Sayfa yeniden yüklendiğinde websocket nesnesi (onclose işleyicili) artık var olmayacak. Sayfanız yüklenirken hemen sayfanızda bir WebSocket bağlantısı kurmaya çalışıyorsanız, eski bağlantının bağlantısı kesildikten çok kısa bir süre sonra sunucunun yeni bir bağlantıyı reddettiği bir sorunla karşılaşıyor olabilirsiniz (veya tarayıcı hazır değildir). bağlanmaya çalıştığınız noktada bağlantı kurmak için) ve yeni websocket nesnesi için bir onclose olayı alıyorsunuz.


2
Firefox'ta bağlantının bir sonraki sayfa yüklemesinde takılı kalması olasıdır. Referans bulamıyorum ama bu konuda bir hata olabileceğini düşünüyorum. Diğer olasılık, onclosekullanıcı gezinirken / sayfa yeniden yüklenirken olayın beklenmedik bir şekilde veya belki bilerek tetiklenmesidir. Ben ettik bir soru haberi doğru ve nasıl otomatik yeniden bağlanma uygulamak o vardır tarayıcı beklenen davranış ne olması gerektiğini soran.
leggetter

4
düşünün bu sorunları ile onbeforeunloadolay
artkoenig


35

İşin aslı, bugün kullanımda olan WebSocket'lerin 2 ana protokol sürümü olmasıdır. [0x00][message][0xFF]Protokolü kullanan eski versiyon ve ardından Hybi formatlı paketleri kullanan yeni versiyon var .

Eski protokol sürümü Opera ve iPod / iPad / iPhone'lar tarafından kullanılır, bu nedenle WebSockets sunucularında geriye dönük uyumluluğun uygulanması gerçekten önemlidir. Eski protokolü kullanan bu tarayıcılarla, sayfayı yenilemenin veya sayfadan uzaklaşmanın veya tarayıcıyı kapatmanın, tarayıcının bağlantıyı otomatik olarak kapatmasıyla sonuçlandığını keşfettim. Harika!!

Ancak yeni protokol sürümünü kullanan tarayıcılarda (örn. Firefox, Chrome ve sonunda IE10), yalnızca tarayıcının kapatılması, tarayıcının bağlantıyı otomatik olarak kapatmasına neden olacaktır. Yani, sayfayı yenilerseniz veya sayfadan uzaklaşırsanız, tarayıcı bağlantıyı otomatik olarak KAPATMAZ. Bununla birlikte, tarayıcının yaptığı şey, sunucuya ilk baytın (proto kimlik) 0x88(daha iyi yakın veri çerçevesi olarak bilinir ) olduğu bir hybi paketi göndermektir . Sunucu bu paketi aldıktan sonra, isterseniz bağlantıyı kendisini zorla kapatabilir.


4
sunucu tarafında pratik bir örnek bu hybi paketini nasıl yönetebilirim?
albanx

9
Bağlantıyı kapatmaması delice görünüyor. WebSocket değişkeni sayfa yeniden yüklendiğinde silinir, öyleyse erişilemezse bağlantı neden açık kalsın? Bağlantının yeniden kullanılması da mantıklı olmaz.
Triynko

@albanx aşağıdan cevabımı kontrol et
artkoenig

Bir websocket istemcisinden (yani Tarayıcı) yakın çerçevenin nasıl gönderileceğine ilişkin herhangi bir kod örneği. Ws npm modülünü kullanıyorum
Shaik Syed Ali

3

Theoobe tarafından belirtildiği gibi , bazı tarayıcılar web yuvalarını otomatik olarak kapatmaz. İstemci tarafında herhangi bir "tarayıcı penceresini kapat" olaylarını işlemeye çalışmayın. Büyük masaüstü VE mobil tarayıcıların desteğini düşünüyorsanız, şu anda bunu yapmanın güvenilir bir yolu yoktur (örneğin onbeforeunload, Mobile Safari'de çalışmayacaktır). Bu sorunu sunucu tarafında ele alma konusunda iyi bir deneyimim oldu. Örneğin, Java EE kullanıyorsanız, javax.websocket.Endpoint'e bir göz atın , tarayıcıya bağlı olarak ya OnCloseyöntem ya da OnErroryöntem, tarayıcı penceresini kapatır / yeniden yüklerseniz çağrılacaktır.


1
Benim durumumda, veri aktarımı sırasında Bağlantı kapanıyor, Opera ve iOS ailesi tarayıcılarında iyi çalışıyor. Lütfen bana yardım et .. Son iki haftadır bu sorunla mücadele ediyorum. stackoverflow.com/q/30799814/2225439
Mrug

2

Gereksinime göre herhangi bir işlevi yazabileceğiniz web soketinin yakın yöntemini kullanarak.

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.