WebSocket
dox_websocket adds a WebSocket server to the Dox HTTP server. Use it for live chat, notifications and other real-time updates.
Want Socket.IO clients?
Use Socket.IO. Turn it on with AppConfig(socketIo: SocketIoConfig(enabled: true)).
It runs on the same port, works with the official Socket.IO clients, and has acks and namespaces.
dox_websocket keeps working next to it.
Usage
1. Create websocket service with redis adapter
class WebsocketService implements DoxService {
@override
void setup() {
Redis sub = Redis();
Redis pub = sub.duplicate();
WebsocketServer io = WebsocketServer(Dox());
io.adapter(WebsocketRedisAdapter(
subscriber: sub,
publisher: pub,
));
}
}
Many isolates need Redis
Dox runs one isolate per CPU core by default. Each isolate has its own memory. Without an adapter, a room only reaches clients on the same isolate.
- Use the Redis adapter. It needs
ioredis^2.0.0-alpha.1. - Or set
totalIsolate: 1inlib/config/app.dart(orAPP_TOTAL_ISOLATE=1).
2. Register websocket service to dox app/config/services.dart
3. Create websocket controller
import 'package:dox_core/dox_core.dart';
import 'package:dox_websocket/dox_websocket.dart';
class ChatWebSocketController {
intro(WebsocketEmitter emitter, dynamic message) {
// sent message to chart room but exclude the sender
emitter.room('chat').emitExceptSender('intro', message);
}
noti(WebsocketEmitter emitter, dynamic message) {
// sent message to chart room including the sender
emitter.room('chat').emit('noti', message);
}
}
Note
As webSocket maintains an open connection, there is no requirement to send back any values from your controller method.
4. register websocket route and events
ChatWebSocketController controller = ChatWebSocketController();
Router.websocket('ws', (WebsocketEvent event) {
// when client sent an event called `intro`,
// it will execute `controller.intro` method
event.on('intro', controller.intro);
// when client sent an event called `noti`,
// it will execute `controller.noti` method
event.on('noti', controller.noti);
});
Info
You can register websocket routes on lib/routes/web.dart or you can also create custom websocket router and register in lib/config/app.dart. Both option will create a websocket url on ws://127.0.0.1:{port}/ws.
Note
You also have the option to register WebSocket routes for multiple paths, rather than just the default /ws route.
Client Usage
You have the option to utilize either the built-in browser WebSocket or any WebSocket library for clients. The key requirement is that when sending data, it must be in the form of a JSON string containing both event and message attributes. Refer to the example below for clarification.
Example with Dart
import 'dart:io';
// The event name that is listening in your routes
// Eg. DoxWebsocket.on('intro', controller.intro);
String event = 'intro';
// Message can be any type such as int, float, map, string etc..
String message = "Mingalaba!";
// Encoding to json formatted string
var data = jsonEncode({
"event": event,
"message": message,
});
String url = 'ws://localhost:3000/ws';
WebSocket socket = await WebSocket.connect(url);
socket.add(data);
// If you would like to join the room, please use event name `joinRoom`
var joinRoomData = jsonEncode({
"event": "joinRoom",
"message": "chat", // sent room name as message
});
// Sent message to join the chat room
socket.add(joinRoomData);
Example with javascript
For Handling with javascript, we suggested you to use below library. https://github.com/dartondox/dox-web-socket-client
import DoxWebsocket from '@dartondox/websocket';
const socket = DoxWebsocket('ws://127.0.0.1:3000/ws', {
maxRetries: 18, retryAfter: 2000
})
socket.onConnected(() => {
console.log(socket.id)
})
socket.onError(() => {
console.log('socket error')
})
// Listen in client for intro event that will sent from the server
socket.on('intro', (msg) => {
console.log(msg)
})
socket.onClose(() => {
console.log('socket closed')
})
function sendMessage(message) {
socket.emit('intro', message)
}
SocketEmitter
room
Set the room before emit to client
Info
Use the same name the client sent with joinRoom.
room() returns a new emitter. The room does not stay set for later events.
emit
Emit to all the client connected to the same websocket route.
emitExceptSender
Emit to all the client connected to the same websocket route except the sender.