Skip to main content
  1. Posts/

Building Real-Time Chat Applications with Socket.IO

·6 mins·
socket.io nodejs socket.io
Table of Contents

Socket.io adalah sebuah pustaka JavaScript yang memungkinkan komunikasi real-time, dua arah, dan berbasis event antara klien dan server. Pustaka ini menjadi pilihan utama untuk pengembangan aplikasi chatting berbasis web dan berbagai aplikasi web interaktif lainnya.

Berikut adalah beberapa keuntungan menggunakan Socket.IO:

  • Komunikasi Read-Time: Memungkinkan pertukaran data instan antara klien dan server.
  • Kompabilitas yang Baik: Dapat bekerja di berbagai browser dan platform dengan dukungan fallback.
  • Komunikasi Berbasis Event: Memfasilitasi pengiriman dan penerimaan event antara klien dan server.
  • Skalabilitas: Dapat menangani banyak koneksi secara bersamaan, cocok untuk aplikasi besar.

Dengan demikian, Socket.io memastikan bahwa aplikasi Anda tetap responsif dan dapat diakses oleh berbagai pengguna, terlepas dari keterbatasan teknologi mereka.

Project initialization
#

Pastikan NodeJS telah terinstall di server.

$ node -v
v20.11.0

Selanjutnya install package express@4

npm install express@4

Lalu test dengan membuat index.js seperti berikut.

const express = require('express');
const { createServer } = require('node:http');

const app = express();
const server = createServer(app);

app.get('/', (req, res) => {
  res.send('<h1>Hello world</h1>');
});

server.listen(3000, () => {
  console.log('server running at http://localhost:3000');
});

Jalankan node index.js.

$ node index.js
server running at http://localhost:3000

Akses http://localhost:3000 dengan browser.

test express

Serving HTML
#

Edit index.js seperti berikut.

const express = require('express');
const { createServer } = require('node:http');
const { join } = require('node:path');

const app = express();
const server = createServer(app);

app.get('/', (req, res) => {
  res.sendFile(join(__dirname, 'index.html'));
});

server.listen(3000, () => {
  console.log('server running at http://localhost:3000');
});

Selanjutnya buat file index.html lalu tambahkan content berikut.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Socket.IO chat</title>
    <style>
      body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }

      #form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
      #input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
      #input:focus { outline: none; }
      #form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }

      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages > li { padding: 0.5rem 1rem; }
      #messages > li:nth-child(odd) { background: #efefef; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>

Jalankan kembali node index.js lalu akses http://localhost:3000

tampilan dashboard chat

Integrating Socket.IO
#

Socket.IO terdiri dari 2 bagian:

  • socket.io: Untuk berintegrasi dengan server HTTP Node.js.
  • socket.io-client: Library klien yang dimuat di sisi browser.

Selama pengembangan, socket.io dapat melayani klien secara otomatis sehingga kita hanya perlu menginstall satu modul.

npm install socket.io

Kemudian edit index.js dengan menambahkan baris berikut.

const express = require('express');
const { createServer } = require('node:http');
const { join } = require('node:path');
const { Server } = require('socket.io');

const app = express();
const server = createServer(app);
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(join(__dirname, 'index.html'));
});

io.on('connection', (socket) => {
  console.log('a user connected');
});

server.listen(3000, () => {
  console.log('server running at http://localhost:3000');
});

Edit index.html dan tambahkan baris berikut sebelum </body>

<script src="/socket.io/socket.io.js"></script>
<script>
  const socket = io();
</script>

Anda bisa menemukan versi lokal dari socket.io.js pada direktori ./node_modules/socket.io/client-dist. Selain itu juga terdapat CDN sebagai pengganti file lokal.

<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>

Jalankan kembali node index.js lalu akses `http://localhost:3000.

$ node index.js
server running at http://localhost:3000
a user connected

Sampai disini Anda telah berhasil mengintegrasikan socket.io sehingga dapat terhubung saat diakses dengan browser.

Tambahkan disconnect event untuk mengetahui sambungan socket telah terputus.

io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

Emitting events
#

Bagian ini kita akan membuat socket.io dapat mengirim dan menerima event apapun yang Anda inginkan.

Edit bagian <script> pada index.html

<script src="/socket.io/socket.io.js"></script>
<script>
  const socket = io();

  const form = document.getElementById('form');
  const input = document.getElementById('input');

  form.addEventListener('submit', (e) => {
    e.preventDefault();
    if (input.value) {
      socket.emit('chat message', input.value);
      input.value = '';
    }
  });
</script>

Kemudian tambahkan baris berikut pada index.js untuk menampilkan chat message event.

io.on('connection', (socket) => {
  socket.on('chat message', (msg) => {
    console.log('message: ' + msg);
  });
});

Jalankan ulang node index.js dan kirimkan pesan dari browser.

$ node index.js
server running at http://localhost:3000
a user connected
message: test pesan

Broadcasting
#

Jika sebelumnya pesan tampil di konsol terminal, selanjutnya kita akan membuat pesan tersebut tampil juga di browser menggunakan metode io.emit()

Edit index.js lalu tambahkan baris berikut.

io.on('connection', (socket) => {
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });
});

Edit bagian <script> pada index.html seperti berikut.

<script src="/socket.io/socket.io.js"></script>
<script>
  const socket = io();

  const form = document.getElementById('form');
  const input = document.getElementById('input');
  const messages = document.getElementById('messages');

  form.addEventListener('submit', (e) => {
    e.preventDefault();
    if (input.value) {
      socket.emit('chat message', input.value);
      input.value = '';
    }
  });

  socket.on('chat message', (msg) => {
    const item = document.createElement('li');
    item.textContent = msg;
    messages.appendChild(item);
    window.scrollTo(0, document.body.scrollHeight);
  });
</script>

Jalankan ulang node index.js dan test kirim pesan dari browser.

Server delivery
#

Bagian ini kita akan mengatur agar setiap pesan tersimpan di dalam DB menggunakan modul SQLite.

Install modul SQLite

npm install sqlite sqlite3

Kemudian edit index.js seperti berikut.

const express = require('express');
const { createServer } = require('node:http');
const { join } = require('node:path');
const { Server } = require('socket.io');
const sqlite3 = require('sqlite3');
const { open } = require('sqlite');

async function main() {
  // open the database file
  const db = await open({
    filename: 'chat.db',
    driver: sqlite3.Database
  });

  // create our 'messages' table (you can ignore the 'client_offset' column for now)
  await db.exec(`
    CREATE TABLE IF NOT EXISTS messages (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        client_offset TEXT UNIQUE,
        content TEXT
    );
  `);

  const app = express();
  const server = createServer(app);
  const io = new Server(server, {
    connectionStateRecovery: {}
  });

  app.get('/', (req, res) => {
    res.sendFile(join(__dirname, 'index.html'));
  });

  io.on('connection', (socket) => {
    socket.on('chat message', async (msg) => {
      let result;
      try {
        // store the message in the database
        result = await db.run('INSERT INTO messages (content) VALUES (?)', msg);
      } catch (e) {
        // TODO handle the failure
        return;
      }
      // include the offset with the message
      io.emit('chat message', msg, result.lastID);
    });
  });

  server.listen(3000, () => {
    console.log('server running at http://localhost:3000');
  });
}

main();

Selanjutnya tambahkan serverOffset untuk menyesuaikan atau menyinkronkan waktu antara server dan client.

index.html

<script>
  const socket = io({
    auth: {
      serverOffset: 0
    }
  });

  const form = document.getElementById('form');
  const input = document.getElementById('input');
  const messages = document.getElementById('messages');

  form.addEventListener('submit', (e) => {
    e.preventDefault();
    if (input.value) {
      socket.emit('chat message', input.value);
      input.value = '';
    }
  });

  socket.on('chat message', (msg, serverOffset) => {
    const item = document.createElement('li');
    item.textContent = msg;
    messages.appendChild(item);
    window.scrollTo(0, document.body.scrollHeight);
    socket.auth.serverOffset = serverOffset;
  });
</script>

index.js

// [...]

io.on('connection', async (socket) => {
  socket.on('chat message', async (msg) => {
    let result;
    try {
      result = await db.run('INSERT INTO messages (content) VALUES (?)', msg);
    } catch (e) {
      // TODO handle the failure
      return;
    }
    io.emit('chat message', msg, result.lastID);
  });

  if (!socket.recovered) {
    // if the connection state recovery was not successful
    try {
      await db.each('SELECT id, content FROM messages WHERE id > ?',
        [socket.handshake.auth.serverOffset || 0],
        (_err, row) => {
          socket.emit('chat message', row.content, row.id);
        }
      )
    } catch (e) {
      // something went wrong
    }
  }
});

// [...]

Jalankan ulang node index.js dan test melalui browser.

Referensi:

Related

Build WhatsApp Bot with whatsapp-web.js
·4 mins
nodejs nodejs
Installing Nodejs
·1 min
nodejs linux nodejs
Serve HTML using Express.js
·1 min
nodejs html nodejs
Command 'ng' not found pada Angular
·1 min
nodejs angular nodejs
Deploy Angular di cPanel
·1 min
cpanel nodejs cpanel angular
Error [ERR_REQUIRE_ESM] NodeJS CPanel
·1 min
nodejs cpanel nodejs