Menutup WebSocket dengan benar (HTML5, Javascript)


127

Saya bermain-main dengan HTML5 WebSockets. Saya bertanya-tanya, bagaimana cara menutup koneksi dengan anggun? Seperti, apa yang terjadi jika pengguna me-refresh halaman, atau hanya menutup browser?

Ada perilaku aneh ketika pengguna hanya me-refresh halaman tanpa menelepon websocket.close()- ketika mereka kembali setelah refresh itu akan mengenai websocket.oncloseacara.

Jawaban:


110

Menurut protokol spec v76 (yang merupakan versi browser dengan implementasi dukungan saat ini):

Untuk menutup koneksi dengan bersih, frame yang hanya terdiri dari byte 0xFF diikuti oleh byte 0x00 dikirim dari satu rekan untuk meminta rekan lain menutup koneksi.

Jika Anda menulis server, Anda harus memastikan untuk mengirim bingkai tutup ketika server menutup koneksi klien. Metode tutup soket TCP yang normal kadang-kadang bisa lambat dan menyebabkan aplikasi berpikir koneksi masih terbuka bahkan saat tidak.

Browser harus benar-benar melakukan ini untuk Anda ketika Anda menutup atau memuat ulang halaman. Namun, Anda dapat memastikan frame dekat dikirim dengan melakukan pengambilan acara sebelumunload:

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

Saya tidak yakin bagaimana Anda bisa mendapatkan acara onclose setelah halaman di-refresh. Objek websocket (dengan onclose handler) tidak akan ada lagi setelah halaman dimuat ulang. Jika Anda segera mencoba membuat koneksi WebSocket pada halaman Anda saat halaman dibuka, maka Anda mungkin mengalami masalah di mana server menolak koneksi baru segera setelah yang lama terputus (atau browser tidak siap untuk membuat koneksi pada titik yang Anda coba sambungkan) dan Anda mendapatkan acara onclose untuk objek websocket baru.


2
Ada kemungkinan bahwa di Firefox koneksi sepertinya berkeliaran ke halaman berikutnya. Saya tidak dapat menemukan referensi tetapi saya pikir mungkin ada bug tentang ini. Kemungkinan lainnya adalah bahwa oncloseacara tersebut dipicu secara tak terduga, atau mungkin dengan sengaja, saat pengguna menavigasi / halaman dimuat ulang. Saya telah memposting pertanyaan yang menanyakan perilaku yang diharapkan, browser mana yang benar dan bagaimana kita menerapkan koneksi ulang otomatis.
leggetter

4
pertimbangkan masalah ini dengan onbeforeunloadacara
artkoenig


35

Masalahnya adalah ada 2 versi protokol utama WebSockets yang digunakan saat ini. Versi lama yang menggunakan [0x00][message][0xFF]protokol, dan kemudian ada versi baru menggunakan paket berformat Hybi .

Versi protokol lama digunakan oleh Opera dan iPod / iPad / iPhone sehingga sebenarnya penting bahwa kompatibilitas mundur diterapkan di server WebSockets. Dengan browser ini menggunakan protokol lama, saya menemukan bahwa menyegarkan halaman, atau menavigasi jauh dari halaman, atau menutup browser, semua mengakibatkan browser secara otomatis menutup koneksi. Bagus!!

Namun dengan browser yang menggunakan versi protokol baru (mis. Firefox, Chrome dan akhirnya IE10), hanya menutup browser akan mengakibatkan browser secara otomatis menutup koneksi. Dengan kata lain, jika Anda me-refresh halaman, atau menavigasi jauh dari halaman, browser TIDAK secara otomatis menutup koneksi. Namun, apa yang dilakukan browser, adalah mengirim paket hybi ke server dengan byte pertama (proto ident) sedang 0x88(lebih dikenal sebagai bingkai data tutup). Setelah server menerima paket ini, ia dapat dengan paksa menutup koneksi itu sendiri, jika Anda memilihnya.


4
contoh praktis di sisi server bagaimana mengelola paket hybi ini?
albanx

9
Tampaknya gila bahwa itu tidak menutup koneksi. Variabel WebSocket dihapus pada pemuatan ulang halaman, jadi mengapa koneksi tetap terbuka jika tidak dapat diakses? Menggunakan kembali koneksi juga tidak masuk akal.
Triynko

@albanx periksa jawaban saya di bawah ini
artkoenig

Sampel kode apa pun tentang cara mengirim bingkai dekat dari klien websocket (yaitu Browser). Saya menggunakan modul ws npm
Shaik Syed Ali

3

Seperti yang disebutkan oleh theoobe , beberapa browser tidak secara otomatis menutup websockets. Jangan mencoba untuk menangani "tutup browser jendela" acara sisi klien. Saat ini tidak ada cara yang dapat diandalkan untuk melakukannya, jika Anda mempertimbangkan dukungan desktop utama dan peramban seluler (mis. Tidak onbeforeunloadakan berfungsi di Mobile Safari). Saya memiliki pengalaman yang baik dalam menangani masalah di sisi server ini. Misalnya jika Anda menggunakan Java EE, lihat di javax.websocket.Endpoint , tergantung pada browser OnClosemetode atau OnErrormetode yang akan dipanggil jika Anda menutup / memuat kembali jendela browser.


1
Dalam kasus saya, Koneksi semakin ditutup selama transfer data, Ini berfungsi dengan baik dalam hal browser keluarga Opera dan iOS. Tolong bantu saya. Saya berjuang dengan masalah ini sejak dua minggu terakhir. stackoverflow.com/q/30799814/2225439
Mrug

2

Dengan menggunakan metode tutup soket web, di mana Anda dapat menulis fungsi apa pun sesuai dengan kebutuhan.

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.