Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dvmatyun/web_socket
dart / flutter webSocket package with statuses and other features
https://github.com/dvmatyun/web_socket
dart flutter flutter-package websocket websockets
Last synced: 7 days ago
JSON representation
dart / flutter webSocket package with statuses and other features
- Host: GitHub
- URL: https://github.com/dvmatyun/web_socket
- Owner: dvmatyun
- License: bsd-3-clause
- Created: 2022-09-04T09:37:52.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-03-04T16:02:28.000Z (8 months ago)
- Last Synced: 2024-08-01T12:18:36.707Z (3 months ago)
- Topics: dart, flutter, flutter-package, websocket, websockets
- Language: Dart
- Homepage: https://pub.dev/packages/websocket_universal
- Size: 108 KB
- Stars: 20
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# websocket_universal
[![CHECKOUT](https://github.com/dvmatyun/web_socket/actions/workflows/checkout.yml/badge.svg)](https://github.com/dvmatyun/web_socket/actions/workflows/checkout.yml)# Dart and Flutter webSocket client package for all the platforms (web, mobile, desktop)
## Easy-to-use interface:
1. Easy-to-use websocket methods and usage examples included!
2. Universal socket status changes stream.
3. Ping delay measurement and easy setup for ping/pong interaction with server!
4. Auto-reconnection feature for `IWebSocketHandler` ws handler.## Contact & support me:
1. [Telegram](https://t.me/DmitriiOk)
2. [LinkedIn](https://www.linkedin.com/in/dvmatyun/)
3. [Support me on patreon](https://www.patreon.com/KonungzRage)## Fast start:
```dart
// ignore_for_file: avoid_print
import 'package:websocket_universal/websocket_universal.dart';/// Example works with Postman Echo server
void main() async {
/// 1. Create webSocket handler:
final textSocketHandler = IWebSocketHandler.createClient(
'wss://ws.postman-echo.com/raw', // Postman echo ws server
SocketSimpleTextProcessor(),
);/// 2. Listen to webSocket messages:
textSocketHandler.incomingMessagesStream.listen((inMsg) {
print('> webSocket got text message from server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});
textSocketHandler.outgoingMessagesStream.listen((inMsg) {
print('> webSocket sent text message to server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});/// 3. Connect & send message:
await textSocketHandler.connect();
textSocketHandler.sendMessage('Hello server!');
await Future.delayed(const Duration(seconds: 4));// 4. Disconnect & close connection:
await textSocketHandler.disconnect('manual disconnect');
textSocketHandler.close();
}
```## #1 Simple example with String messages (from and to server):
You don't need your own ws server to run this code.
[Example postman echo server](https://blog.postman.com/introducing-postman-websocket-echo-service/) is used in this example.1. Send message to server using `sendMessage(Y messageToServer)` and
listen messages coming from server using `incomingMessagesStream`
2. Listen to websocket states `socketStateStream`
or all events that are happening `logEventStream`.
Define how you process your messages to and from server and ping/pong interaction
using `IMessageProcessor` generic interface or use convinient
`SocketMessageProcessor` implementation (see example #2).```dart
import 'package:websocket_universal/websocket_universal.dart';/// Example works with Postman Echo server
void main() async {
/// Postman echo ws server (you can use your own server URI)
/// 'wss://ws.postman-echo.com/raw'
/// For local server it could look like 'ws://127.0.0.1:42627/websocket'
const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
const textMessageToServer = 'Hello server!';
const connectionOptions = SocketConnectionOptions(
pingIntervalMs: 3000, // send Ping message every 3000 ms
timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms
/// see ping/pong messages in [logEventStream] stream
skipPingMessages: false,/// Set this attribute to `true` if do not need any ping/pong
/// messages and ping measurement. Default is `false`
pingRestrictionForce: false,
);/// Example with simple text messages exchanges with server
/// (not recommended for applications)
/// [] generic types mean that we receive [String] messages
/// after deserialization and send [String] messages to server.
final IMessageProcessor textSocketProcessor =
SocketSimpleTextProcessor();
final textSocketHandler = IWebSocketHandler.createClient(
websocketConnectionUri, // Postman echo ws server
textSocketProcessor,
connectionOptions: connectionOptions,
);// Listening to webSocket status changes
textSocketHandler.socketHandlerStateStream.listen((stateEvent) {
// ignore: avoid_print
print('> status changed to ${stateEvent.status}');
});// Listening to server responses:
textSocketHandler.incomingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket got text message from server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});// Listening to debug events inside webSocket
textSocketHandler.logEventStream.listen((debugEvent) {
// ignore: avoid_print
print('> debug event: ${debugEvent.socketLogEventType}'
' [ping=${debugEvent.pingMs} ms]. Debug message=${debugEvent.message}');
});// Listening to outgoing messages:
textSocketHandler.outgoingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket sent text message to server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});// Connecting to server:
final isTextSocketConnected = await textSocketHandler.connect();
if (!isTextSocketConnected) {
// ignore: avoid_print
print('Connection to [$websocketConnectionUri] failed for some reason!');
return;
}textSocketHandler.sendMessage(textMessageToServer);
await Future.delayed(const Duration(seconds: 30));
// Disconnecting from server:
await textSocketHandler.disconnect('manual disconnect');
// Disposing webSocket:
textSocketHandler.close();
}```
## #2 Recommended way to exchange messages with server (typed Messages):
You don't need your own ws server to run this code.
[Example postman echo server](https://blog.postman.com/introducing-postman-websocket-echo-service/) is used in this example.```dart
import 'package:websocket_universal/websocket_universal.dart';void main() async {
/// Postman echo ws server (you can use your own server URI)
/// For local server it could look like 'ws://127.0.0.1:42627/websocket'
const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
const textMessageToServer = 'Hello server!';
const connectionOptions = SocketConnectionOptions(
pingIntervalMs: 3000, // send Ping message every 3000 ms
timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms
/// see ping/pong messages in [logEventStream] stream
skipPingMessages: false,
);/// Complex example:
/// Example using [ISocketMessage] and [IMessageToServer]
/// (recommended for applications, server must deserialize
/// [ISocketMessage] serialized string to [ISocketMessage] object)
final IMessageProcessor, IMessageToServer>
messageProcessor = SocketMessageProcessor();
final socketHandler =
IWebSocketHandler, IMessageToServer>.createClient(
websocketConnectionUri,
messageProcessor,
connectionOptions: connectionOptions,
);// Listening to debug events inside webSocket
socketHandler.logEventStream.listen((debugEvent) {
// ignore: avoid_print
print('> debug event: ${debugEvent.socketLogEventType}'
' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');
});// Listening to webSocket status changes
socketHandler.socketStateStream.listen((stateEvent) {
// ignore: avoid_print
print('> status changed to ${stateEvent.status}');
});// [IMessageToServer] also implements [ISocketMessage] interface.
// So basically we are sending and receiving equally-typed messages.
const messageTypeStr = '[ISocketMessage]';
// Listening to server responses:
socketHandler.incomingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket got $messageTypeStr: $inMsg');
});// Listening to outgoing messages:
socketHandler.outgoingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket sent $messageTypeStr: $inMsg');
});// Connecting to server:
final isConnected = await socketHandler.connect();if (!isConnected) {
// ignore: avoid_print
print('Connection to [$websocketConnectionUri] failed for some reason!');
return;
}// Sending message with routing path 'test' and simple JSON payload:
final outMsg = MessageToServerImpl.onlyHost(
host: 'test',
data: '{"payload": "$textMessageToServer"}',
error: null,
);
socketHandler.sendMessage(outMsg);await Future.delayed(const Duration(seconds: 8));
// Disconnecting from server:
await socketHandler.disconnect('manual disconnect');
// Disposing webSocket:
socketHandler.close();
}
```## #3 Handling byte messages (from and to server) on client side:
```dart
import 'dart:convert';import 'package:websocket_universal/websocket_universal.dart';
/// Bytes array example:
void main() async {
/// For getting/answering byte-array messages (`List in dart`)
/// you will need your own server and handle messages as byte-arrays
/// on the backend side too. On client side it will look like this:
const websocketLocalExample = 'ws://127.0.0.1:42627/websocket';
const textMessageToServer = 'Hello server!';
const connectionOptions = SocketConnectionOptions(
pingIntervalMs: 3000, // send Ping message every 3000 ms
timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms
/// see ping/pong messages in [logEventStream] stream
skipPingMessages: false,
);final IMessageProcessor, List> bytesSocketProcessor =
SocketSimpleBytesProcessor();
final bytesSocketHandler =
IWebSocketHandler, List>.createClient(
websocketLocalExample, // Local ws server
bytesSocketProcessor,
connectionOptions: connectionOptions,
);// Listening to debug events inside webSocket
bytesSocketHandler.logEventStream.listen((debugEvent) {
// ignore: avoid_print
print('> debug event: ${debugEvent.socketLogEventType}'
' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');
});// Listening to server responses:
bytesSocketHandler.incomingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket got bytes message from server: "$inMsg"');
});// Listening to outgoing messages:
bytesSocketHandler.outgoingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket sent bytes message to server: "$inMsg"');
});// Connecting to server:
final isBytesSocketConnected = await bytesSocketHandler.connect();
if (!isBytesSocketConnected) {
// ignore: avoid_print
print('Connection to [$websocketLocalExample] for bytesSocketHandler '
'failed for some reason!');
return;
}
final bytesMessage = utf8.encode(textMessageToServer);
//textMessageToServer
bytesSocketHandler.sendMessage(bytesMessage);await Future.delayed(const Duration(seconds: 7));
// Disconnecting from server:
await bytesSocketHandler.disconnect('manual disconnect');
// Disposing webSocket:
bytesSocketHandler.close();
}```
## #4 Advanced ISocketMessage handling. Composite server response example:
```dart
import 'dart:convert';import 'package:websocket_universal/websocket_universal.dart';
void main() async {
/// Postman echo ws server (you can use your own server URI)
/// For local server it could look like 'ws://127.0.0.1:42627/websocket'
const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
const connectionOptions = SocketConnectionOptions(
pingIntervalMs: 3000, // send Ping message every 3000 ms
timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms
/// see ping/pong messages in [logEventStream] stream
skipPingMessages: false,
);/// Complex example:
/// Example using [ISocketMessage] and [IMessageToServer]
/// (recommended for applications, server must deserialize
/// [ISocketMessage] serialized string to [ISocketMessage] object)
final IMessageProcessor, IMessageToServer>
messageProcessor = SocketMessageProcessor();
final socketHandler =
IWebSocketHandler, IMessageToServer>.createClient(
websocketConnectionUri,
messageProcessor,
connectionOptions: connectionOptions,
);/// Creating websocket_manager:
/// `ISocketManagerMiddleware` processes requests before sending and
/// after receiving ISocketMessage. See test implementation for details.
final ISocketManagerMiddleware middleware = SocketManagerMiddleware();
final IWebSocketRequestManager requestManager = WebSocketRequestManager(
middleware: middleware,
webSocketHandler: socketHandler,
);
final IWebSocketDataBridge dataBridge = WebSocketDataBridge(requestManager);///
// Connecting to server:
final isConnected = await socketHandler.connect();if (!isConnected) {
// ignore: avoid_print
print('Connection to [$websocketConnectionUri] failed for some reason!');
return;
}// Sending message with routing path 'test' and simple JSON payload:
final requestGame = MessageToServerImpl.duo(
host: TestDecoder.host,
topic1: CustomGameModel.topic1,
data: jsonEncode(
const CustomGameModel(
name: 'MakeWorld strategy',
playersAmount: 8,
),
),
error: null,
);
final socketRequest = SocketRequest(requestMessage: requestGame);final result =
await dataBridge.singleRequestFull(socketRequest);
// ignore: avoid_print
print('Got result: ${result.data}');final outMsgList = MessageToServerImpl.duo(
host: TestDecoder.host,
topic1: CustomGameModel.topic1List,
data: jsonEncode([
const CustomGameModel(
name: 'MakeWorld strategy',
playersAmount: 8,
),
const CustomGameModel(
name: 'New patch',
playersAmount: 4,
),
]),
error: null,
);
final socketRequestList = SocketRequest(requestMessage: outMsgList);final listResult = await dataBridge
.singleRequestFull>(socketRequestList);
// ignore: avoid_print
print('Got list result: ${listResult.data}');// Creating composite request with 2 response topics required
final topicSingle = SocketTopicImpl.duo(
host: TestDecoder.host,
topic1: CustomGameModel.topic1,
);
final topicList = SocketTopicImpl.duo(
host: TestDecoder.host,
topic1: CustomGameModel.topic1List,
);
// Assemple composite request, that, in fact, requests CustomGameModel
// using [requestGame] to request single game and awaits to receive 2 topics
// from server: [topicSingle] and [topicList]
final compositeRequest = SocketRequest(
requestMessage: requestGame,
responseTopics: {topicSingle, topicList},
);
// Running task:
final compositeTask = dataBridge.compositeRequest(compositeRequest);
// Emulating server 2nd response (real server should response with 2
// messages without 2nd request)
dataBridge.requestData(socketRequestList);
final compositeResp = await compositeTask;// In result we can get multiple results from composite response:
final responseOne = compositeResp.getData();
final responseTwo = compositeResp.getData>();// ignore: avoid_print
print('Got composite result. Answers = ${compositeResp.dataCached.length}'
'[$responseOne] and [$responseTwo]');// Disconnecting from server:
await socketHandler.disconnect('manual disconnect');
// Disposing webSocket:
requestManager.close();
socketHandler.close();
}```
[Source repository](https://github.com/dvmatyun/web_socket)