dart_node_ws
dart_node_ws provides type-safe WebSocket bindings for Node.js, enabling real-time bidirectional communication in your Dart applications.
Installation
dependencies:
dart_node_ws: ^0.2.0
Also install the ws package via npm:
npm install ws
Quick Start
WebSocket Server
import 'package:dart_node_ws/dart_node_ws.dart';
void main() {
final server = createWebSocketServer(port: 8080);
server.on('connection', (WebSocketClient client) {
print('Client connected');
client.on('message', (data) {
print('Received: $data');
// Echo back
client.send('You said: $data');
});
client.on('close', () {
print('Client disconnected');
});
// Send welcome message
client.send('Welcome to the WebSocket server!');
});
print('WebSocket server running on port 8080');
}
Integrating with Express
import 'package:dart_node_express/dart_node_express.dart';
import 'package:dart_node_ws/dart_node_ws.dart';
void main() {
final app = createExpressApp();
final httpServer = app.listen(3000);
// Attach WebSocket server to the HTTP server
final wss = createWebSocketServer(server: httpServer);
wss.on('connection', (WebSocketClient client) {
// Handle WebSocket connections
});
// HTTP routes still work
app.get('/', (req, res) {
res.send('HTTP server with WebSocket support');
});
}
WebSocket Server API
Creating a Server
// Standalone server on a port
final server = createWebSocketServer(port: 8080);
// Attached to an existing HTTP server
final server = createWebSocketServer(server: httpServer);
// With path filtering
final server = createWebSocketServer(
server: httpServer,
path: '/ws', // Only accept connections to /ws
);
Server Events
server.on('connection', (WebSocketClient client, Request req) {
// New client connected
// req contains the HTTP upgrade request
print('Connection from ${req.headers['origin']}');
});
server.on('error', (error) {
print('Server error: $error');
});
server.on('close', () {
print('Server closed');
});
Broadcasting to All Clients
void broadcast(String message) {
for (final client in server.clients) {
if (client.readyState == WebSocket.OPEN) {
client.send(message);
}
}
}
WebSocket Client API
Client Events
client.on('message', (data) {
// Handle incoming message
// data can be String or Buffer
});
client.on('close', (code, reason) {
print('Closed with code $code: $reason');
});
client.on('error', (error) {
print('Client error: $error');
});
client.on('ping', (data) {
// Ping received (pong sent automatically)
});
client.on('pong', (data) {
// Pong received (response to our ping)
});
Sending Messages
// Send text
client.send('Hello, client!');
// Send JSON
client.send(jsonEncode({'type': 'update', 'data': someData}));
// Send binary data
client.send(Uint8List.fromList([0x01, 0x02, 0x03]));
Client State
// Check connection state
if (client.readyState == WebSocket.OPEN) {
client.send('Connected!');
}
// States: CONNECTING, OPEN, CLOSING, CLOSED
Closing Connection
// Close gracefully
client.close();
// Close with code and reason
client.close(1000, 'Normal closure');
Chat Server Example
import 'package:dart_node_ws/dart_node_ws.dart';
import 'package:dart_node_express/dart_node_express.dart';
void main() {
final app = createExpressApp();
// Serve static files for the chat client
app.use(staticMiddleware('public'));
final httpServer = app.listen(3000, () {
print('Server running on http://localhost:3000');
});
// WebSocket server
final wss = createWebSocketServer(server: httpServer);
final clients = <String, WebSocketClient>{};
wss.on('connection', (WebSocketClient client) {
String? username;
client.on('message', (data) {
final message = jsonDecode(data);
switch (message['type']) {
case 'join':
username = message['username'];
clients[username!] = client;
broadcast({
'type': 'system',
'text': '$username joined the chat',
});
break;
case 'message':
if (username != null) {
broadcast({
'type': 'message',
'username': username,
'text': message['text'],
'timestamp': DateTime.now().toIso8601String(),
});
}
break;
}
});
client.on('close', () {
if (username != null) {
clients.remove(username);
broadcast({
'type': 'system',
'text': '$username left the chat',
});
}
});
});
void broadcast(Map<String, dynamic> message) {
final json = jsonEncode(message);
for (final client in clients.values) {
if (client.readyState == WebSocket.OPEN) {
client.send(json);
}
}
}
}
Real-time Dashboard Example
import 'dart:async';
import 'package:dart_node_ws/dart_node_ws.dart';
void main() {
final server = createWebSocketServer(port: 8080);
final subscribers = <WebSocketClient>{};
// Simulate real-time data updates
Timer.periodic(Duration(seconds: 1), (_) {
final data = {
'timestamp': DateTime.now().toIso8601String(),
'cpu': Random().nextDouble() * 100,
'memory': Random().nextDouble() * 100,
'requests': Random().nextInt(1000),
};
final json = jsonEncode(data);
for (final client in subscribers) {
if (client.readyState == WebSocket.OPEN) {
client.send(json);
}
}
});
server.on('connection', (WebSocketClient client) {
print('Dashboard client connected');
subscribers.add(client);
// Send initial state
client.send(jsonEncode({
'type': 'init',
'serverTime': DateTime.now().toIso8601String(),
}));
client.on('close', () {
subscribers.remove(client);
print('Dashboard client disconnected');
});
});
print('Dashboard WebSocket server on port 8080');
}
Error Handling
server.on('connection', (WebSocketClient client) {
client.on('message', (data) {
try {
final message = jsonDecode(data);
// Process message...
} catch (e) {
client.send(jsonEncode({
'error': 'Invalid message format',
}));
}
});
client.on('error', (error) {
print('Client error: $error');
// Don't crash the server
});
});
server.on('error', (error) {
print('Server error: $error');
// Handle server-level errors
});
API Reference
See the full API documentation for all available functions and types.