What is WebSocket?

WebSocket là một giao thức hai chiều, full duplex (song công toàn phần - việc giao tiếp giữa bên gửi và bên nhận có thể diễn ra đồng thời) được khởi tạo bởi HTTP.

What is the Difference Between HTTP and WebSockets?

Đa số các giao tiếp giữa trình duyệt và website sử dụng HTTP. Với HTTP, client sẽ gửi request và server trả về response. Thường thì response được trả về ngay lập tức và transaction (tương tự như transaction trong database) sẽ được hoàn thành. Tất cả các cặp request và response sẽ tồn tại trong các transaction độc lập với nhau.

WebSocket được khởi tạo bởi HTTP và thường tồn tại lâu. Các thông điệp có thể được gửi bởi cả hai chiều bất kể lúc nào. Kết nối sẽ luôn mở và trong trạng thái nhàn rỗi cho đến khi client hoặc server sẵn sàng để gửi thông điệp.

WebSocket thường được sử dụng cho các ứng dụng cần trao đổi thông điệp với độ trễ thấp chẳng hạn như các ứng dụng stream dữ liệu thời gian thực.

How Are WebSocket Connections Established?

Kết nối WebSocket có thể được tạo ra bởi JS như sau:

var ws = new WebSocket("wss://normal-website.com/chat");

Note

Giao thức wss là WebSocket trên TLS (có mã hóa) còn ws thì không có mã hóa.

Để thiết lập kết nối, trình duyệt và server cần thực hiện việc bắt tay WebSocket thông qua HTTP. Trình duyệt sẽ gửi đi một WebSocket handshake request như sau:

GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket

Nếu server chấp nhận kết nối thì nó sẽ trả về một WebSocket handshake response như sau:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=

Tại thời điểm này, kết nối đã được mở và thông điệp có thể được gửi từ cả hai chiều.

Info

  • Header ConnectionUpgrade trong request và response cho biết đây là một WebSocket handshake.
  • Header Sec-WebSocket-Version chỉ định phiên bản WebSocket mà client muốn dùng, thường là version 13.
  • Header Sec-WebSocket-Key là một giá trị ngẫu nhiên cơ số 64 được tạo mới đối với mỗi handshake request.
  • Header Sec-WebSocket-Accept trong response là giá trị hash của header Sec-WebSocket-Key nối với một chuỗi cụ thể được định nghĩa trong đặc tả của giao thức. Header này giúp ngăn các response bị sai lệch khi server hoặc proxy bị cấu hình sai.

What Do WebSocket Messages Look Like?

Một message đơn giản có thể được gửi thông qua JS như sau:

ws.send("Peter Wiener");

Theo nguyên lý, các thông điệp WebSocket có thể chứa bất kỳ dữ liệu hoặc định dạng dữ liệu nào. JSON là định dạng dữ liệu thường được dùng trong các ứng dụng hiện đại. Ví dụ, một ứng dụng chatbot sử dụng WebSocket có thể gửi một thông điệp có dạng như sau:

{"user":"Hal Pline","content":"I wanted to be a Playstation growing up, not a device to answer your inane questions"}

Set up a WebSocket Server in Node.js

Server Side

Trước tiên, thiết lập một project NodeJS và add package ws:

yarn init
yarn add ws

Code phía server:

import { WebSocketServer } from 'ws';
 
const wss = new WebSocketServer({ port: 8080 });
 
wss.on('connection', function connection(ws) {
  ws.on('message', function message(data) {
    console.log('client: %s', data);
  });
 
  ws.send('server: hello');
});

Có thể thấy, WebSocket server sẽ chạy trên port 8080.

Client Side

Code ở phía client dùng để tương tác với server:

<body>
  <form id="form" action="">
    <input id="input" autocomplete="off" /><button>Send</button>
  </form>
 
  <script>
    window.onload = function () {
      const ws = new WebSocket('ws://localhost:8080');
      ws.onopen = function () {
        console.log('WebSocket Client Connected');
      };
      ws.onmessage = function (event) {
        console.log(event.data);
      }
 
      const form = document.getElementById('form');
      form.addEventListener("submit", function (event) {
        input = document.getElementById('input');
        ws.send(input.value);
        event.preventDefault();
        input.value = '';
      });
    }
  </script>
</body>
list
from outgoing([[WebSocket]])
sort file.ctime asc

Resources