Hoàn thành bài "Hiểu về Giao thức WebSocket và sự khác biệt với HTTP" trước để mở khoá bài này.Đến bài trước

Giới thiệu

WebSocket là một giao thức cho phép kết nối song công, kết nối bền vững giữa máy khách và máy chủ qua một socket TCP duy nhất. Khác với HTTP thuần túy nơi client phải gửi yêu cầu và server trả về, kết nối WebSocket duy trì mở và cả hai bên có thể gửi tin nhắn bất cứ lúc nào. Điều này làm cho nó hoàn hảo cho ứng dụng chat, bảng điều khiển thời gian thực, trò chơi nhiều người chơi và bất kỳ tính năng nào cần cập nhật thời gian thực.

Trong bài học này bạn sẽ xây dựng thiết lập WebSocket nhỏ nhất có thể: một máy chủ bằng Node.js sử dụng thư viện `ws` phổ biến, và một client trình duyệt kết nối với nó và trao đổi vài tin nhắn. Không dùng framework, không cơ sở dữ liệu — chỉ giao thức thô để bạn hiểu những gì đang diễn ra từ bên trong.

Thiết lập Dự án

Tạo một thư mục mới cho dự án và khởi tạo nó. Bạn cần cài đặt Node.js (phiên bản 18 hoặc cao hơn là được).

bash
mkdir ws-demo
cd ws-demo
npm init -y
npm install ws

Gói `ws` là một triển khai WebSocket nhanh, được sử dụng rộng rãi cho Node.js. Sau khi chạy `npm install`, bạn sẽ có một thư mục `node_modules` và một `package.json` liệt kê `ws` là một phụ thuộc.

Viết máy chủ

Tạo một file có tên `server.js`. Máy chủ thực hiện ba việc: nhập thư viện, tạo một máy chủ WebSocket được gán vào một cổng, và xác định điều gì sẽ xảy ra khi có kết nối và khi nhận tin nhắn.

javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('A client connected');
ws.on('message', (data) => {
const text = data.toString();
console.log('Received:', text);
ws.send(`Server echo: ${text}`);
});
ws.send('Welcome to the WebSocket server!');
});
console.log('WebSocket server is listening on ws://localhost:8080');

Sự kiện `connection` được kích hoạt mỗi lần có một khách hàng kết nối. Callback nhận một đối tượng `ws` đại diện cho socket của từng khách hàng cụ thể. Bên trong callback bạn gán một listener `message`. Khi một tin nhắn đến, `data` mặc định là một Buffer, vì vậy `toString()` chuyển nó thành văn bản thuần túy. Máy chủ sau đó gửi lại tin nhắn được gán tiền tố `Server echo:`.

Chạy máy chủ với `node server.js`. Bạn sẽ thấy dòng nhật ký "listening" và không có gì khác cho đến khi có một client kết nối.

sơ đồ luồng kết nối — client gửi CONNECT, server chấp nhận, hai bên gửi MESSAGE qua lại trên cùng một socket duy nhất

Viết Browser Client

Tạo một file có tên `index.html`. Trình duyệt có thể mở kết nối WebSocket bằng đối tượng toàn cục tích hợp `WebSocket` — không cần thư viện ở phía client.

markup
<!DOCTYPE html>
<html>
<head><title>WebSocket Demo</title></head>
<body>
<h1>WebSocket Demo</h1>
<input id="msg" placeholder="Type a message" />
<button id="send">Send</button>
<ul id="log"></ul>
<script>
const log = document.getElementById('log');
const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener('open', () => {
log.innerHTML += '<li>Connected to server</li>';
});
ws.addEventListener('message', (event) => {
log.innerHTML += '<li>From server: ' + event.data + '</li>';
});
document.getElementById('send').addEventListener('click', () => {
const input = document.getElementById('msg');
ws.send(input.value);
input.value = '';
});
</script>
</body>
</html>

Sự kiện `open` kích hoạt khi tiến trình bắt tay hoàn tất. Sau đó, `ws.send('text')` gửi một chuỗi đến server. Phản hồi được server gợi lại sẽ nhận về dưới dạng sự kiện `message` mà `event.data` là chuỗi mà server đã gửi.

Kiểm thử End-to-End

Chạy máy chủ với `node server.js`. Sau đó mở `index.html` trong trình duyệt của bạn (có thể nhấp đúp vào file, hoặc dùng công cụ như `npx serve`). Trong terminal bạn sẽ thấy "A client connected" ngay lúc trang được tải. Gõ gì đó vào hộp input và nhấp Gửi. Nhật ký trình duyệt sẽ hiển thị tin nhắn của bạn được tiền tố bởi `Server echo:`, và terminal sẽ ghi nhận mỗi thông điệp mà server nhận.

Những sai lầm phổ biến

Quên gọi `data.toString()` ở phía server sẽ trả về một đối tượng Buffer thô thay vì chuỗi có thể đọc được mà client gửi. Quên tiền tố giao thức `ws://` trong URL trình duyệt sẽ gây ra lỗi cú pháp vì constructor `WebSocket` đòi URL đầy đủ bao gồm scheme. Nếu server chưa chạy, sự kiện `open` của trình duyệt sẽ không bao giờ kích hoạt và bạn sẽ thấy không có log — luôn kiểm tra terminal trước khi có điều gì đó xảy ra.

Tóm tắt

Bây giờ bạn có một máy chủ echo WebSocket hoạt động và một client trình duyệt. Server dùng `ws` để lắng nghe trên cport 8080, chấp nhận kết nối và lặp lại bất kỳ tin nhắn nào nhận được. Client mở kết nối với `new WebSocket('ws://localhost:8080')` và dùng `send` cùng các sự kiện `message` để giao tiếp. Mô hình này — một máy chủ, nhiều client kết nối, tin nhắn hai chiều — là nền tảng mà mọi tính năng thời gian thực đều dựa vào.

Luyện tập sau buổi học

Bài kiểm tra cuối bài

Ôn lại kiến thức, thử sức và nhận góp ý cho bài làm.

0/1
Đã trả lời · 0/1
Xây dựng máy chủ WebSocket đầu tiên của bạn với thư viện ws