Tạo và vận hành dự án Socket.io với ServBay
Socket.io là một thư viện JavaScript phổ biến, được thiết kế để xây dựng các ứng dụng web thời gian thực, hai chiều và dựa trên sự kiện. Dựa trên giao thức WebSocket, Socket.io còn cung cấp các cơ chế fallback (như long polling) khi cần thiết, đảm bảo kết nối ổn định, đáng tin cậy trong nhiều điều kiện khách hàng và mạng khác nhau.
Hướng dẫn này sẽ giúp bạn thiết lập, chạy và quản lý dự án Socket.io với sự hỗ trợ mạnh mẽ từ môi trường phát triển local của ServBay. ServBay cung cấp môi trường Node.js được cấu hình sẵn và các công cụ quản lý website tiện lợi, giúp phát triển Socket.io hiệu quả hơn bao giờ hết.
Socket.io là gì?
Socket.io là thư viện giúp hiện thực hóa cơ chế giao tiếp thời gian thực, hai chiều và dựa trên sự kiện. Thư viện này gồm hai thành phần:
- Một thư viện phía backend chạy trên Node.js server.
- Một thư viện JavaScript phía client chạy trên trình duyệt.
Mặc dù sử dụng WebSocket làm mục tiêu chính, Socket.io có khả năng tự động phát hiện và fallback sang các phương thức truyền khác (như Adobe Flash Socket, Ajax Long Polling, Ajax Multipart Streaming, Forever IFrame, JSONP Polling v.v.) để đảm bảo khả năng tương thích với trình duyệt cũ hoặc mạng hạn chế.
Đặc điểm và lợi ích chính của Socket.io
- Giao tiếp thời gian thực: Trao đổi dữ liệu tức thì giữa client và server; lý tưởng cho chat, cộng tác, dashboard thời gian thực, game trực tuyến, v.v.
- Hỗ trợ đa nền tảng: Hoạt động tốt trên trình duyệt web, ứng dụng di động lẫn môi trường server Node.js.
- Tự động kết nối lại: Nếu mất kết nối mạng, client sẽ tự động thử kết nối lại server, tăng độ ổn định cho ứng dụng.
- Dựa trên sự kiện: Mô hình lập trình hướng sự kiện giúp xử lý bất đồng bộ trở nên trực quan và dễ quản lý.
- Phòng và Namespace: Hỗ trợ group các client vào “phòng” để gửi/broadcast thông điệp tới nhóm cụ thể; “namespace” cho phép tái sử dụng kết nối và đa luồng trên cùng một socket.
- Hỗ trợ dữ liệu nhị phân: Gửi và nhận dữ liệu nhị phân dễ dàng.
- Khả năng tương thích cao: Nhiều cơ chế vận chuyển đảm bảo tin cậy trong mọi điều kiện mạng.
Với Socket.io, lập trình viên có thể tập trung vào logic ứng dụng mà không lo về những chi tiết phức tạp của giao tiếp thời gian thực phía dưới.
Tạo và chạy dự án Socket.io trên ServBay
ServBay mang đến môi trường Node.js “ready to use” cho lập trình viên, tích hợp sẵn runtime Node.js, npm và công cụ quản lý website. Chúng ta sẽ tận dụng các tiện ích này để thiết lập và vận hành ví dụ dự án Socket.io sau đây.
Điều kiện tiên quyết
Trước khi bắt đầu, hãy đảm bảo bạn đã hoàn thành:
- Cài đặt ServBay: Tải và cài đặt ServBay mới nhất từ website chính thức của ServBay.
- Cài đặt gói Node.js trong ServBay: Kiểm tra Node.js đã được cài trong ServBay chưa, thông qua mục “Phần mềm” (trước đây gọi là dịch vụ). Tham khảo tài liệu Sử dụng Node.js trong ServBay để biết chi tiết cách cài đặt.
Tạo dự án Socket.io mẫu
Chúng ta sẽ thực hiện một ứng dụng chat đơn giản làm ví dụ.
Khởi tạo thư mục dự án:
Mở terminal. ServBay khuyến khích lưu dự án website tại
/Applications/ServBay/www
. Đến thư mục này, tạo folder dự án mới, khởi tạo Node.js project và cài đặt các package cần thiết:bashcd /Applications/ServBay/www mkdir servbay-socketio-chat cd servbay-socketio-chat npm init -y npm install express socket.io
1
2
3
4
5Thao tác này sẽ tạo file
package.json
trong folderservbay-socketio-chat
và cài hai package quan trọng:express
(cung cấp file tĩnh và xử lý HTTP) vàsocket.io
(server lẫn client).Tạo file server (
server.js
):Trong thư mục gốc dự án
servbay-socketio-chat
, tạo fileserver.js
và copy đoạn mã dưới đây. File này dùng để khởi động HTTP server, tích hợp Socket.io và lắng nghe/gửi thông điệp giữa client-server.javascriptconst express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const path = require('path'); // Nhúng module path const app = express(); // Tạo HTTP server dựa trên ứng dụng express const server = http.createServer(app); // Gắn Socket.io vào HTTP server const io = socketIo(server); // Thiết lập thư mục tĩnh trỏ về thư mục hiện tại app.use(express.static(__dirname)); // Xử lý yêu cầu GET về root, trả về file index.html app.get('/', (req, res) => { // Sử dụng path.join đảm bảo đường dẫn đúng trên mọi hệ điều hành res.sendFile(path.join(__dirname, 'index.html')); }); // Lắng nghe sự kiện kết nối từ Socket.io io.on('connection', (socket) => { console.log('a user connected'); // Log khi có user kết nối mới // Lắng nghe sự kiện disconnect socket.on('disconnect', () => { console.log('user disconnected'); // Log khi user ngắt kết nối }); // Lắng nghe sự kiện 'chat message' socket.on('chat message', (msg) => { console.log('message: ' + msg); // Log tin nhắn nhận được // Phát (broadcast) tin nhắn cho mọi client kết nối io.emit('chat message', msg); }); }); // Lấy port từ biến môi trường hoặc port mặc định const port = process.env.PORT || 3000; server.listen(port, () => { console.log(`Server running on port ${port}`); console.log(`Access it via http://localhost:${port} (direct) or via ServBay reverse proxy`); });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43Giải thích mã:
- Sử dụng
express
tạo web server đơn giản phục vụ fileindex.html
. http.createServer(app)
tạo HTTP server nền tảng cho Socket.io tích hợp.socketIo(server)
khởi tạo Socket.io và gắn nó vào HTTP server.io.on('connection', ...)
lắng nghe kết nối client mới.socket.on('disconnect', ...)
lắng nghe khi client ngắt kết nối.socket.on('chat message', ...)
nhận sự kiện "chat message" từ client.io.emit('chat message', msg)
phát tin nhắn tới tất cả client đang kết nối.
- Sử dụng
Tạo file client (
index.html
):Trong thư mục dự án, tạo file
index.html
và copy đoạn mã sau. File này gồm bố cục HTML, CSS và mã JavaScript client dùng để kết nối, gửi, hiện tin nhắn trực tiếp từ server.html<!DOCTYPE html> <html> <head> <title>ServBay 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; } .servbay-banner { background-color: #007bff; /* Xanh dương ServBay */ color: white; text-align: center; padding: 15px 0; font-size: 22px; margin-bottom: 20px; font-weight: bold; } </style> </head> <body> <div class="servbay-banner">Chào mừng đến với demo chat Socket.io của ServBay!</div> <ul id="messages"></ul> <form id="form" action=""> <input id="input" autocomplete="off" /><button type="submit">Gửi</button> </form> <!-- Nhúng thư viện Socket.io client --> <!-- File này do server Socket.io tự sinh động tại runtime --> <script src="/socket.io/socket.io.js"></script> <script> // Kết nối với server Socket.io // Nếu client & server cùng domain và port, io() sẽ tự động kết nối var socket = io(); var form = document.getElementById('form'); var input = document.getElementById('input'); var messages = document.getElementById('messages'); // Lấy phần tử messages form.addEventListener('submit', function(e) { e.preventDefault(); // Ngăn hành vi submit mặc định if (input.value) { // Gửi sự kiện 'chat message' và nội dung ra server socket.emit('chat message', input.value); input.value = ''; // Xoá ô input } }); // Lắng nghe sự kiện 'chat message' từ server gửi về socket.on('chat message', function(msg) { // Tạo mục li mới để hiển thị tin nhắn var item = document.createElement('li'); item.textContent = msg; // Dùng textContent chống XSS messages.appendChild(item); // Thêm tin vào danh sách // Scroll đến tin nhắn mới nhất window.scrollTo(0, document.body.scrollHeight); }); </script> </body> </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64Giải thích mã:
- Trang gồm bố cục HTML đơn giản, một ít CSS (có banner màu thương hiệu ServBay), một danh sách chat (
ul#messages
) và form gửi tin nhắn (form#form
). <script src="/socket.io/socket.io.js"></script>
nhúng thư viện client của Socket.io (tự động cung cấp bởi server khi chạy).io()
khởi động kết nối với server.- Lắng nghe, gửi sự kiện, xử lý các tin nhắn chat đến, đi thông qua JavaScript.
- Trang gồm bố cục HTML đơn giản, một ít CSS (có banner màu thương hiệu ServBay), một danh sách chat (
Như vậy, bạn đã hoàn thành việc viết mã cho dự án mẫu Socket.io. Tiếp theo, chúng ta sẽ chạy và truy cập ứng dụng này với ServBay.
Chạy dự án qua ServBay (chế độ phát triển)
Ở giai đoạn phát triển, bạn sẽ trực tiếp chạy Node.js server, sau đó sử dụng chức năng reverse proxy của ServBay để ánh xạ ứng dụng này ra một domain local.
Chạy server Node.js ở chế độ dev:
Mở terminal, chuyển thư mục về
/Applications/ServBay/www/servbay-socketio-chat
rồi chạy lệnh sau để khởi động server (dùng port 8585, có thể thay đổi tuỳ ý):bashcd /Applications/ServBay/www/servbay-socketio-chat PORT=8585 node server.js
1
2Nếu thành công, sẽ hiện dòng như
Server running on port 8585
trên terminal, nghĩa là server đang listen port 8585 local.Cấu hình website (reverse proxy) trên ServBay:
Để tiện lợi sử dụng domain local và hỗ trợ HTTPS, bạn cần cấu hình reverse proxy trên ServBay:
- Mở bảng điều khiển ServBay.
- Vào mục "Website".
- Nhấn Thêm website mới.
- Thiết lập:
- Tên (Name):
ServBay Socket.io Dev
(hoặc tên tuỳ ý) - Domain:
servbay-socketio-dev.servbay.demo
(hoặc domain.servbay.demo
nào bạn muốn) - Loại website: Chọn
Reverse Proxy
- Proxy destination: Nhập
http://127.0.0.1:8585
(trỏ về port Node.js đang chạy dev)
- Tên (Name):
- Lưu lại. ServBay sẽ tự áp dụng cấu hình và có thể khởi động lại web server liên quan (Caddy hoặc Nginx, tuỳ cấu hình).
Lưu ý: Reverse proxy cực kỳ quan trọng với Socket.io vì không chỉ forward HTTP thông thường mà còn hỗ trợ WebSocket. Cấu hình Caddy/Nginx tích hợp của ServBay đã bao gồm việc proxy WebSocket tự động.
Tham khảo thêm Thêm website Node.js chế độ Dev để biết chi tiết từng bước; hoặc Bảo vệ website bằng SSL/TLS để bật chứng chỉ HTTPS cho domain local. ServBay User CA lẫn ServBay Public CA đều có thể được dùng tạo, tin cậy chứng chỉ local.
Truy cập website chế độ Dev:
Mở trình duyệt và nhập domain bạn vừa config, ví dụ:
https://servbay-socketio-dev.servbay.demo
. Giao diện chat sẽ hiện ra, thử mở nhiều tab/trình duyệt hoặc thiết bị cùng địa chỉ để kiểm tra chat thời gian thực.
Triển khai dự án qua ServBay (chế độ sản xuất)
Ở môi trường production, bạn nên chạy Node.js với process manager (như PM2, forever…), đồng thời liên kết ngược qua reverse proxy của ServBay. Dưới đây trình bày ví dụ phần cấu hình reverse proxy ServBay, giả sử rằng app Node.js đã được chạy ổn định ở một port nhất định.
Khởi động server Node.js ở chế độ prod:
Trong môi trường thực tế, bạn nên dùng process manager để đảm bảo app luôn chạy nền, tự restart khi có sự cố. Ví dụ dùng PM2:
bash# Nếu chưa cài PM2 # npm install pm2 -g cd /Applications/ServBay/www/servbay-socketio-chat PORT=8586 NODE_ENV=production pm2 start server.js --name servbay-socketio-prod
1
2
3
4
5Lệnh này khởi chạy
server.js
với PM2, port 8586, env "production". PM2 sẽ đảm nhận quản lý tiến trình lâu dài.Cấu hình website reverse proxy chế độ prod:
Giống bước ở chế độ dev, tạo website reverse proxy mới trên ServBay trỏ về port Node.js đã chạy ở chế độ prod.
- Mở bảng điều khiển ServBay.
- Vào mục "Website".
- Thêm website mới.
- Thiết lập:
- Tên (Name):
ServBay Socket.io Prod
(hoặc tên nhận biết khác) - Domain:
servbay-socketio-prod.servbay.demo
(hoặc domain.servbay.demo
bất kỳ) - Loại website: Chọn
Reverse Proxy
- Proxy destination: Nhập
http://127.0.0.1:8586
(trỏ về port Node.js chạy sản xuất)
- Tên (Name):
- Lưu lại.
Truy cập website chế độ Prod:
Mở trình duyệt và vào domain chế độ sản xuất, ví dụ:
https://servbay-socketio-prod.servbay.demo
.
Nhờ reverse proxy của ServBay, bạn có thể dễ dàng quản lý (dev/prod) nhiều app Node.js khác nhau, tuỳ biến ssl, domain local mà không cần chỉnh sửa hosts file hay cấu hình web server phức tạp thủ công.
Kết nối các cơ sở dữ liệu do ServBay cung cấp
ServBay hỗ trợ nhiều gói database, như MySQL, MariaDB, PostgreSQL, MongoDB, Redis. Ứng dụng Socket.io của bạn có thể kết nối các database này để lưu trữ thông tin user, lịch sử tin nhắn…, dưới đây là ví dụ kết nối cụ thể bằng Node.js.
Lưu ý: Trước tiên hãy đảm bảo gói database bạn cần đã được cài và khởi động trong ServBay. Thông tin kết nối mặc định (port, user, password,...) tham khảo tại giao diện quản lý database hoặc tài liệu ServBay. Mật khẩu gốc root của MySQL/MariaDB thường được thiết lập khi cài. Bạn cũng có thể reset password root qua công cụ của ServBay.
Kết nối MongoDB:
Cài đặt thư viện Mongoose ODM (hoặc driver gốc
mongodb
):bashnpm install mongoose
1Thêm đoạn kết nối trong mã Node.js của bạn (ví dụ ở
server.js
hoặc module database riêng):javascriptconst mongoose = require('mongoose'); // Mặc định kết nối MongoDB local (port 27017) // Database: servbay_socketio_app là ví dụ mongoose.connect('mongodb://localhost:27017/servbay_socketio_app', { useNewUrlParser: true, useUnifiedTopology: true, // Thêm user, pass nếu cần xác thực // user: 'your_mongo_user', // pass: 'your_mongo_password' }) .then(() => console.log('Kết nối MongoDB thành công qua Mongoose')) .catch(err => console.error('Lỗi kết nối MongoDB:', err)); // Sẵn sàng định nghĩa Schema và Model với mongoose.model() // ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Kết nối Redis:
Cài client Redis:
bashnpm install redis
1Thêm đoạn kết nối:
javascriptconst redis = require('redis'); // Tạo Redis client, mặc định connect localhost:6379 const client = redis.createClient({ // Nếu Redis cần xác thực password // password: 'your_redis_password', // url: 'redis://localhost:6379' }); client.on('error', (err) => { console.error('Lỗi kết nối Redis:', err); }); client.on('connect', () => { console.log('Kết nối Redis thành công'); }); // Kết nối Redis server client.connect(); // Redis v4+ cần gọi connect() // Có thể dùng client thực thi các lệnh Redis // VD: await client.set('mykey', 'myvalue'); // ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23Kết nối MariaDB / MySQL:
ServBay đồng thời hỗ trợ MariaDB và MySQL. Sử dụng thư viện
mariadb
(tương thích cả MySQL):Cài lib client:
bashnpm install mariadb
1Thêm đoạn kết nối:
javascriptconst mariadb = require('mariadb'); // Tạo pool kết nối const pool = mariadb.createPool({ host: 'localhost', port: 3306, // Port mặc định MariaDB/MySQL user: 'root', // User default trong ServBay password: 'password', // Đổi thành mật khẩu thực tế đã cài database: 'servbay_socketio_app', // Tên db ví dụ connectionLimit: 5 // Số kết nối tối đa pool }); // Lấy kết nối để test pool.getConnection() .then(conn => { console.log("Kết nối MariaDB/MySQL thành công"); conn.release(); // Trả lại kết nối về pool // Sẵn sàng thực thi query với pool // VD: await pool.query("SELECT 1"); // ... }) .catch(err => { console.error("Lỗi kết nối MariaDB/MySQL:", err); });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24Chú ý: Hãy thay đổi
password
đúng với mật khẩu user root của bạn trong ServBay. Khuyến cáo nên tạo user mới cho app thay vì dùng luôn root.Kết nối PostgreSQL:
Cài thư viện client
pg
:bashnpm install pg
1Đoạn kết nối:
javascriptconst { Pool } = require('pg'); // Tạo pool kết nối const pool = new Pool({ user: 'user', // User mặc định, thay bằng user thật tế host: 'localhost', database: 'servbay_socketio_app', // Tên db ví dụ password: 'password', // Đổi pass đúng đã cài trong ServBay port: 5432, // Port PostgreSQL mặc định }); // Lấy kết nối để test pool.connect((err, client, done) => { if (err) { console.error('Lỗi kết nối PostgreSQL:', err); return; } console.log('Kết nối PostgreSQL thành công'); client.release(); // Trả lại kết nối về pool // Sẵn sàng thực thi query với pool // VD: pool.query('SELECT NOW()', (err, res) => { ... }); // ... });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23Chú ý: Đảm bảo điền đúng
user
vàpassword
đã set trong ServBay cho PostgreSQL.
Việc tích hợp các hệ quản trị cơ sở dữ liệu này giúp ứng dụng Socket.io của bạn có thể lưu dữ liệu bền vững, mở rộng chức năng. Với ServBay, việc dựng môi trường phát triển Node.js và database tại local cực kỳ nhanh chóng.
Một số lưu ý khi sử dụng
- Xung đột port: Hãy kiểm tra chắc chắn port Node.js sử dụng (ví dụ 8585, 8586) không bị ứng dụng khác chiếm dụng. Nếu bị trùng, đổi
PORT
biến môi trường. - Cấu hình website trên ServBay: Cấu hình reverse proxy xong, hãy chắc chắn web server ServBay (Caddy/Nginx) đã được restart và áp dụng cấu hình mới.
- Proxy WebSocket: Reverse proxy trên ServBay mặc định hỗ trợ nâng cấp WebSocket. Nếu gặp lỗi kết nối WebSocket, hãy xem lại log hoặc cấu hình Caddy/Nginx đảm bảo WebSocket proxy đúng.
- Tường lửa (Firewall): Đảm bảo firewall hệ điều hành không chặn port 80, 443 hoặc port Node.js của bạn.