Masalah: Koneksi klien-server dan server-klien dengan latensi rendah
Web sebagian besar telah dibuat berdasarkan paradigma permintaan/respons HTTP. Klien memuat halaman web, lalu tidak ada yang terjadi hingga pengguna mengklik halaman berikutnya. Sekitar tahun 2005, AJAX mulai membuat web terasa lebih dinamis. Namun, semua komunikasi HTTP diarahkan oleh klien, yang memerlukan interaksi pengguna atau polling berkala untuk memuat data baru dari server.
Teknologi yang memungkinkan server untuk mengirim data ke klien tepat pada saat server mengetahui bahwa data baru telah tersedia telah cukup lama digunakan. Namanya antara lain 'Push' atau 'Comet'. Salah satu hack yang paling umum untuk menciptakan ilusi koneksi yang dimulai server disebut long polling. Dengan polling panjang, klien membuka koneksi HTTP ke server yang membuatnya tetap terbuka hingga mengirim respons. Setiap kali server benar-benar memiliki data baru, server akan mengirimkan respons (teknik lainnya melibatkan permintaan Flash, multibagian XDR, dan disebut juga htmlfiles). Polling panjang dan teknik lainnya bekerja dengan cukup baik. Anda menggunakannya setiap hari dalam aplikasi seperti obrolan Gmail.
Namun, semua solusi ini memiliki satu masalah: Mereka membawa overhead HTTP, yang tidak membuatnya cocok untuk aplikasi berlatensi rendah. Misalnya, game first-person shooter multipemain di browser atau game online lainnya dengan komponen real-time.
Memperkenalkan WebSocket: Membawa soket ke web
Spesifikasi WebSocket menentukan API yang membuat koneksi "soket" antara browser web dan server. Dengan kata sederhana: Ada koneksi persisten antara klien dan server dan kedua pihak dapat mulai mengirim data kapan saja.
Memulai
Anda membuka koneksi WebSocket hanya dengan memanggil konstruktor WebSocket:
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
Perhatikan ws:
. Ini adalah skema URL baru untuk koneksi WebSocket. Ada juga
wss:
untuk koneksi WebSocket aman dengan cara yang sama seperti https:
yang digunakan untuk koneksi HTTP
aman.
Melampirkan beberapa pengendali peristiwa dengan segera ke koneksi memungkinkan Anda mengetahui kapan koneksi dibuka, menerima pesan masuk, atau terjadi error.
Argumen kedua menerima sub-protokol opsional. Nilai bisa berupa string atau array string. Setiap string harus mewakili nama sub-protokol dan server hanya menerima salah satu sub-protokol yang diteruskan dalam array. Sub-protokol yang diterima dapat ditentukan dengan mengakses properti protocol
objek WebSocket.
Nama sub-protokol harus berupa salah satu nama sub-protokol yang terdaftar di registry IANA. Saat ini hanya ada satu nama sub-protokol (soap) yang terdaftar sejak Februari 2012.
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
Berkomunikasi dengan server
Segera setelah memiliki koneksi ke server (saat peristiwa open
diaktifkan), kita dapat mulai mengirim data ke server menggunakan metode send('your message')
pada objek koneksi. Sebelumnya hanya mendukung string, tetapi dalam spesifikasi terbaru, sekarang juga dapat mengirim pesan biner. Untuk mengirim data biner, Anda dapat menggunakan objek Blob
atau ArrayBuffer
.
// Sending String
connection.send('your message');
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
// Sending file as Blob
var file = document.querySelector('input[type="file"]').files[0];
connection.send(file);
Server dengan cara yang sama mungkin juga mengirimkan pesan kepada kami. Setiap kali hal ini terjadi, callback onmessage
akan diaktifkan. Callback menerima objek peristiwa dan pesan sebenarnya dapat diakses melalui properti data
.
WebSocket juga dapat menerima pesan biner dalam spesifikasi terbaru. Frame biner dapat diterima dalam format Blob
atau ArrayBuffer
. Untuk menentukan format biner yang diterima, tetapkan properti binaryType objek WebSocket ke 'blob' atau 'arraybuffer'. Format default-nya adalah 'blob'. (Anda tidak perlu menyelaraskan parameter binaryType saat mengirim.)
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};
Fitur lain yang baru ditambahkan ke WebSocket adalah ekstensi. Dengan menggunakan ekstensi, Anda dapat mengirim frame yang dikompresi, multipleks, dll. Anda dapat menemukan ekstensi yang diterima server dengan memeriksa properti ekstensi objek WebSocket setelah peristiwa terbuka. Belum ada spesifikasi ekstensi yang dipublikasikan secara resmi mulai Februari 2012.
// Determining accepted extensions
console.log(connection.extensions);
Komunikasi lintas origin
Sebagai protokol modern, komunikasi lintas origin sudah terintegrasi langsung ke dalam WebSocket. Meskipun Anda tetap harus memastikan untuk hanya berkomunikasi dengan klien dan server yang Anda percayai, WebSocket memungkinkan komunikasi antar pihak di domain apa pun. Server memutuskan apakah akan menyediakan layanannya untuk semua klien atau hanya klien yang berada di kumpulan domain yang ditentukan dengan baik.
Server proxy
Setiap teknologi baru memiliki serangkaian masalah baru. Pada kasus WebSocket kompatibilitas dengan server proxy yang memediasi koneksi HTTP di sebagian besar jaringan perusahaan. Protokol WebSocket menggunakan sistem upgrade HTTP (yang biasanya digunakan untuk HTTP/SSL) untuk 'mengupgrade' koneksi HTTP ke koneksi WebSocket. Beberapa server proxy tidak menyukai hal ini dan akan memutuskan koneksi. Jadi, meskipun klien tertentu menggunakan protokol WebSocket, kemungkinan tidak mungkin untuk membuat koneksi. Hal ini membuat bagian berikutnya menjadi lebih penting :)
Menggunakan WebSocket sekarang
WebSocket masih merupakan teknologi baru dan belum sepenuhnya diterapkan di semua browser. Namun, Anda dapat menggunakan WebSocket saat ini dengan library yang menggunakan salah satu penggantian yang disebutkan di atas setiap kali WebSocket tidak tersedia. Library yang menjadi sangat populer di domain ini adalah socket.io yang dilengkapi dengan klien dan implementasi server protokol dan menyertakan fallback (socket.io belum mendukung pengiriman pesan biner sejak Februari 2012). Ada juga solusi komersial seperti PusherApp yang dapat diintegrasikan dengan mudah ke dalam lingkungan web mana pun dengan menyediakan API HTTP untuk mengirim pesan WebSocket ke klien. Karena permintaan HTTP tambahan, akan selalu ada overhead tambahan dibandingkan dengan WebSocket murni.
Sisi server
Penggunaan WebSocket akan menciptakan pola penggunaan yang sama sekali baru untuk aplikasi sisi server. Meskipun stack server tradisional seperti LAMP dirancang berdasarkan siklus permintaan/respons HTTP, stack tersebut sering kali tidak menangani banyak koneksi WebSocket terbuka dengan baik. Mempertahankan banyak koneksi terbuka secara bersamaan memerlukan arsitektur yang menerima konkurensi tinggi dengan biaya performa yang rendah. Arsitektur tersebut biasanya dirancang berdasarkan threading atau yang disebut IO non-blocking.
Implementasi sisi server
- Node.js
- Java
- Ruby
- Python
- Erlang
- C++
- .NET
Versi protokol
Protokol wire (handshake dan transfer data antara klien dan server) untuk WebSocket sekarang menjadi RFC6455. Chrome dan Chrome untuk Android terbaru sepenuhnya kompatibel dengan RFC6455, termasuk pesan biner. Selain itu, Firefox akan kompatibel pada versi 11, Internet Explorer pada versi 10. Anda tetap dapat menggunakan versi protokol yang lebih lama, tetapi tidak direkomendasikan karena diketahui rentan. Jika Anda memiliki implementasi server untuk protokol WebSocket versi lama, sebaiknya upgrade ke versi terbaru.
Kasus penggunaan
Gunakan WebSocket setiap kali Anda membutuhkan latensi yang benar-benar rendah, koneksi mendekati realtime antara klien dan server. Perlu diingat bahwa hal ini mungkin melibatkan pemikiran ulang tentang cara Anda mem-build aplikasi sisi server dengan fokus baru pada teknologi seperti antrean peristiwa. Beberapa contoh kasus penggunaannya adalah:
- Game online multiplayer
- Aplikasi obrolan
- Ticker olahraga live
- Streaming media sosial yang diperbarui secara real-time
Demo
- Plink
- Paint With Me
- Pixelatr
- Garis putus-putus
- Teka-teki online multiplayer yang besar
- Server ping (digunakan dalam contoh di atas)
- Contoh demo HTML5