Belajar WebSocket - WebSocket Server dengan Node.js (ws library)
Episode 5 of 34

Belajar WebSocket - WebSocket Server dengan Node.js (ws library)

Episode ini membangun server WebSocket dengan library ws: instalasi, pembuatan server, event connection dan message, broadcast ke semua klien, serta manajemen koneksi dengan identifikasi dan pembersihan.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Di episode 4 kalian punya klien. Sekarang waktunya membangun sisi yang melayani: server WebSocket. Kita memakai ws, library Node.js paling populer untuk protokol ini.

Library ws ringan dan mendekati protokol asli — tidak ada lapisan reconnection otomatis atau room. Justru itu kelebihannya: kalian akan memahami cara kerja WebSocket yang sebenarnya sebelum melapisinya dengan kemudahan Socket.IO di episode 6. Di episode ini kalian akan membuat server, menangani event, broadcast pesan, dan mengelola banyak klien.

Instalasi dan Setup Server

Membuat Project dan Menginstall ws

Mulai dari project kosong:

Install library ws
mkdir ws-server
cd ws-server
npm init -y
npm install ws

Perintah npm install ws menarik library beserta dependency-nya yang minim. Setelah ini, kalian siap menulis server pertama.

Server WebSocket Paling Dasar

JSServer WebSocket pertama
const { WebSocketServer } = require("ws");
 
const wss = new WebSocketServer({ port: 8080 });
 
wss.on("connection", (ws) => {
  console.log("klien terhubung");
  ws.send("selamat datang");
});

new WebSocketServer({ port: 8080 }) membuat server yang mendengarkan koneksi di port 8080. Event connection dipanggil setiap kali handshake selesai, membawa objek ws milik klien tersebut.

Event Handling di Server

Event connection, message, close, dan error

Server berkomunikasi lewat event. Berikut handler yang wajib kalian kenal:

JSEvent handling lengkap
wss.on("connection", (ws) => {
  ws.on("message", (data, isBinary) => {
    console.log("terima:", data.toString());
    ws.send("pesan diterima");
  });
 
  ws.on("close", () => {
    console.log("klien pergi");
  });
 
  ws.on("error", (err) => {
    console.error("error:", err.message);
  });
 
  ws.on("pong", () => {
    console.log("pong diterima");
  });
});

ws.on("message", handler) dipanggil untuk setiap frame data. Argumen isBinary membedakan text dan binary frame. Event pong hanya aktif jika server memakai heartbeat — dibahas di episode 11.

Perbedaan Data Text dan Binary

Karena ws bisa menerima dua tipe data:

JSMembedakan text dan binary
ws.on("message", (data, isBinary) => {
  if (isBinary) {
    console.log("data biner:", data);
  } else {
    console.log("teks:", data.toString());
  }
});

Cek isBinary menentukan cara menafsirkan data, yang di ws berupa Buffer untuk binary dan Buffer atau string untuk text.

Sending dan Broadcasting

Unicast: Kirim ke Satu Klien

Untuk mengirim ke klien tertentu, kalian perlu menyimpan referensinya:

JSUnicast dan broadcast
const wss = new WebSocketServer({ port: 8080 });
const klien = new Map();
 
wss.on("connection", (ws) => {
  klien.set(ws, new Date());
 
  ws.on("message", (data) => {
    const pesan = data.toString();
    for (const [k] of klien) {
      k.send(pesan);
    }
  });
});

Mengulang for (const [k] of klien) dan memanggil k.send(pesan) pada semua entri adalah broadcast manual. Karena tidak ada API broadcast di ws, kalian membangunnya sendiri — persis yang akan dipermudah Socket.IO.

Menyimpan dan Membersihkan Klien

Tanpa pembersihan, klien yang sudah putus akan tetap menganggur di memori:

JSPembersihan klien putus
ws.on("close", () => {
  klien.delete(ws);
  console.log("klien tersisa:", klien.size);
});

Selalu panggil klien.delete(ws) di event close. Ukuran klien.size juga berguna sebagai metrik jumlah koneksi aktif — cikal bakal monitoring di episode 18.

Konfigurasi dan Keterbatasan

Opsi Konfigurasi Server

WebSocketServer menerima berbagai opsi:

  • port atau server: port mandiri atau server HTTP yang sudah ada.
  • maxPayload: batas ukuran payload, misalnya 100e6 untuk 100MB.
  • perMessageDeflate: mengaktifkan kompresi permessage-deflate.
  • clientTracking: melacak daftar klien di wss.clients.

Menggabungkan dengan server HTTP memberi keuntungan besar: satu port melayani API REST dan WebSocket.

JSServer HTTP dan WebSocket bersama
const http = require("http");
const { WebSocketServer } = require("ws");
 
const server = http.createServer((req, res) => {
  res.writeHead(200);
  res.end("server jalan");
});
 
const wss = new WebSocketServer({ server });
 
wss.on("connection", (ws) => {
  ws.send("halo dari port yang sama");
});
 
server.listen(8080);

Dengan new WebSocketServer({ server }), satu server HTTP di port 8080 melayani keduanya. Inilah pola yang dipakai aplikasi production.

Tip

Setel maxPayload selalu. Tanpa batas, klien bisa mengirim payload raksasa dan memakan memori server — salah satu celah DoS yang akan kita bahas di episode 19.

Penutup

Episode 5 memberi kalian server WebSocket yang fungsional: instalasi ws, pembuatan server, handling event connection dan message, unicast dan broadcast manual, serta manajemen daftar klien yang bersih dari kebocoran memori.

Inti yang harus dibawa pulang:

  • Library ws ringan dan dekat dengan protokol asli RFC 6455.
  • Event kunci: connection, message, close, error, dan pong.
  • Broadcast harus dibangun manual dengan melacak daftar klien.
  • Selalu hapus klien yang sudah putus untuk mencegah memory leak.
  • Gabungkan server HTTP dan WebSocket untuk satu port.
  • Setel maxPayload sejak awal untuk keamanan.

Di episode 6 selanjutnya kita memperkenalkan Socket.IO — library yang melapisi WebSocket dengan reconnection otomatis, fallback, room, dan namespace. Kalian akan melihat kapan memakai Socket.IO dan kapan tetap memakai ws murni.