1. Tổng quan về giao tiếp thời gian thực (Real-time Communication)
Giao tiếp thời gian thực là hình thức trao đổi dữ liệu giữa client và server mà không cần yêu cầu thủ công từ phía người dùng (ví dụ: không cần nhấn nút “Làm mới”). Thay vào đó, dữ liệu được đẩy đến client ngay khi có thay đổi ở phía server.

Ví dụ thực tiễn:
- Chat online
- Bảng giá chứng khoán
- Trạng thái người dùng (online/offline)
- Game nhiều người chơi
1.1. Vấn đề của HTTP truyền thống
Giao thức HTTP hoạt động theo mô hình request-response: client gửi request → server trả response → kết thúc kết nối.
Nhược điểm:
- Không phù hợp với ứng dụng cần dữ liệu cập nhật liên tục
- Client không biết khi nào có thay đổi ở server
-
Nếu dùng
polling
(client gửi request mỗi vài giây), sẽ gây lãng phí tài nguyên mạng và không kịp thời
1.2. WebSocket – giải pháp thời gian thực
WebSocket là giao thức giúp thiết lập một kết nối hai chiều (bi-directional) và liên tục (persistent) giữa client và server.

Ưu điểm:
- Giao tiếp theo thời gian thực
- Không cần request lại mỗi lần
- Tối ưu về tốc độ và tài nguyên
2. Socket.IO là gì?
Socket.IO là một thư viện JavaScript cung cấp giao tiếp thời gian thực giữa client và server, được xây dựng dựa trên WebSocket, đồng thời hỗ trợ fallback (long-polling…) nếu WebSocket không khả dụng.
2.1. Ưu điểm nổi bật
- Đa nền tảng: hoạt động với trình duyệt, Node.js, Flutter, Unity…
- Giao tiếp hai chiều (real-time)
- Quản lý kết nối ổn định: tự động reconnect, heartbeat
- API đơn giản dựa trên event (emit / on)
- Hỗ trợ phân nhóm (room, namespace)
3. Kiến trúc ứng dụng chat dùng Socket.IO
Sơ đồ luồng dữ liệu:
Client Flutter (socket_io_client) <---> Socket.IO Server (Node.js + Express)
- Khi người dùng nhập tin nhắn → gửi qua WebSocket đến server
- Server tiếp nhận → phát lại tin nhắn cho tất cả client khác
- Các client lắng nghe → cập nhật UI ngay tức thì
4. Khởi tạo server Node.js với Socket.IO
4.1. Cài đặt
npm init -y
npm install express socket.io
4.2. Code server (index.js)
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: '*'
}
});
io.on('connection', (socket) => {
console.log('Client connected:', socket.id);
socket.on('chat_message', (msg) => {
console.log(`Message from ${socket.id}: ${msg}`);
io.emit('chat_message', msg); // phát lại cho tất cả client
});
socket.on('disconnect', () => {
console.log('Client disconnected:', socket.id);
});
});
server.listen(3000, () => {
console.log('Server listening on http://localhost:3000');
});
Giải thích:
-
io.on('connection')
: bắt sự kiện khi có client kết nối -
socket.on('chat_message')
: lắng nghe sự kiện gửi tin -
io.emit(...)
: phát sự kiện đến tất cả client (broadcast) -
disconnect
: xử lý khi client rời đi
5. Tạo Flutter app và tích hợp Socket.IO
![[Flutter Radiation 6] #2. Gửi và nhận dữ liệu giữa NodeJS server và app Flutter thông qua socket.io](https://i.ytimg.com/vi/HFcOLVwR_po/hq720.jpg?sqp=-oaymwEhCK4FEIIDSFryq4qpAxMIARUAAAAAGAElAADIQj0AgKJD&rs=AOn4CLCYGkxO7udrW1Oa6uflcHbwR9EC0w)
5.1. Tạo project Flutter
flutter create socketio_chat
cd socketio_chat
5.2. Thêm dependency
Trong pubspec.yaml
:
dependencies:
socket_io_client: ^2.0.3+1
flutter:
sdk: flutter
flutter pub get
6. Quản lý kết nối socket trong Flutter
Tạo file socket_service.dart
:
import 'package:socket_io_client/socket_io_client.dart' as IO;
class SocketService {
late IO.Socket socket;
void connect() {
socket = IO.io(
'http://localhost:3000',
IO.OptionBuilder()
.setTransports(['websocket']) // bắt buộc
.disableAutoConnect() // kết nối thủ công
.build(),
);
socket.connect();
socket.onConnect((_) => print('Connected'));
socket.onDisconnect((_) => print('Disconnected'));
}
void sendMessage(String message) {
socket.emit('chat_message', message);
}
void onMessage(Function(dynamic) callback) {
socket.on('chat_message', callback);
}
void dispose() {
socket.dispose();
}
}
7. Xây dựng giao diện Flutter

Trong main.dart
:
import 'package:flutter/material.dart';
import 'socket_service.dart';
void main() {
runApp(ChatApp());
}
class ChatApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Socket.IO Chat',
home: ChatPage(),
);
}
}
class ChatPage extends StatefulWidget {
@override
State<ChatPage> createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
final _controller = TextEditingController();
final List<String> _messages = [];
final SocketService _socketService = SocketService();
@override
void initState() {
super.initState();
_socketService.connect();
_socketService.onMessage((msg) {
setState(() => _messages.add(msg));
});
}
@override
void dispose() {
_socketService.dispose();
super.dispose();
}
void _sendMessage() {
if (_controller.text.trim().isNotEmpty) {
_socketService.sendMessage(_controller.text);
_controller.clear();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat thời gian thực')),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (_, index) => ListTile(title: Text(_messages[index])),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(child: TextField(controller: _controller)),
IconButton(icon: Icon(Icons.send), onPressed: _sendMessage),
],
),
)
],
),
);
}
}
8. Một số lưu ý kỹ thuật
8.1. Vấn đề localhost
Nếu chạy trên thiết bị thật (không phải trình giả lập), localhost
sẽ trỏ vào thiết bị đó, không phải máy tính bạn đang chạy Node.js.
→ Hãy dùng địa chỉ IP nội bộ của máy:
socket = IO.io('http://192.168.x.x:3000', ...);
Kiểm tra bằng:
ipconfig (Windows)
ifconfig (macOS/Linux)
8.2. Sự khác biệt giữa emit
và on
Phía | Hàm | Mục đích |
---|---|---|
client | emit | gửi sự kiện về server |
client | on | lắng nghe sự kiện từ server |
server | emit | gửi sự kiện về client |
server | on | lắng nghe sự kiện từ client |
9. Hướng mở rộng
-
Gửi tên người dùng kèm tin nhắn (
{user: 'A', message: 'Xin chào'}
) -
Sử dụng
room
để tạo chat riêng - Hiển thị thời gian gửi (datetime format)
- Lưu trữ lịch sử chat bằng Firebase hoặc MongoDB
- Xử lý reconnect và hiển thị trạng thái người dùng online
10. Kết luận
Việc xây dựng ứng dụng chat giúp bạn nắm vững:
- Kiến trúc client-server
- Giao tiếp WebSocket thời gian thực
- Quản lý trạng thái, sự kiện, và bất đồng bộ trong Flutter
Socket.IO cung cấp một giao diện đơn giản để bạn dễ dàng hiện thực hóa các ứng dụng real-time chuyên nghiệp, và kết hợp với Flutter, bạn hoàn toàn có thể xây dựng các sản phẩm chất lượng cao, hiệu suất tốt, và tương tác thời gian thực mạnh mẽ.
Nếu bạn đang tìm cách tích hợp tính năng real-time vào ứng dụng Flutter, thì phần chia sẻ dưới đây là dành cho bạn.
Thầy Duy đã thử nghiệm, tinh chỉnh và triển khai thành công giải pháp Socket.IO trong môi trường Flutter.
Với kinh nghiệm giảng dạy và thực chiến của mình, Thầy Duy sẽ hướng dẫn lại toàn bộ quá trình theo cách dễ hiểu nhất, giúp bạn không chỉ làm được mà còn hiểu sâu cách Socket.IO vận hành phía sau.
- Link youtube: https://www.youtube.com/@LeHongDuyCNTT
- Link github: https://github.com/DuyLeHong
📌 Đăng ký ngay tại: https://laptrinh-online.vn/course/lap-trinh-flutter-co-ban
Địa chỉ: Trung tâm CodeFresher – số 104 Hoàng Ngân, Cầu Giấy, Hà Nội.
Hotline: 0813188668 – 0332026803 (zalo / call)
Trả lời