I would like to avoid using the package web_socket_channel which despite its vote doesn't seem to not be actively maintained (many github issues not answered) and doesn't handle errors.
I simply need to connect from Flutter to my WebSocket API in AWS.
How can i do that with dart:io package ? Or is it possible with socket_io_client ? I see that the connection is with http and not wss.
I have found a way in addition to the usual try - catch to handle error in the channel.sink.listen StreamSubscription object with the web_socket_channel package.
You can do the following according to this answer :
_channel = IOWebSocketChannel.connect(
'ws://yourserver.com:port',
);
///
/// Start listening to new notifications / messages
///
_channel.stream.listen(
(dynamic message) {
debugPrint('message $message');
},
onDone: () {
debugPrint('ws channel closed');
},
onError: (error) {
debugPrint('ws error $error');
},
);
This actually works and there is no need to use SocketIO in my use case of course.
I recommend you to use this multiplatform websocket package https://pub.dev/packages/websocket_universal . There you can even use low-level webSocket interactions.
Complete example:
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)
/// [<String, String>] generic types mean that we receive [String] messages
/// after deserialization and send [String] messages to server.
final IMessageProcessor<String, String> textSocketProcessor =
SocketSimpleTextProcessor();
final textSocketHandler = IWebSocketHandler<String, String>.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<void>.delayed(const Duration(seconds: 30));
// Disconnecting from server:
await textSocketHandler.disconnect('manual disconnect');
// Disposing webSocket:
textSocketHandler.close();
}
Related
I need to handle all request except those sent from the service server.
At present, I do it using such a way: capture all requests and into handler filter service requests.
await client.Fetch.enable({
patterns: [
{ requestStage: 'Request' },
{ requestStage: 'Response' }
], // handle all requests and responses.
});
client.Fetch.on('requestPaused', async (event: RequestPausedEvent) => {
if (isServiceRoute(event.request.url))
await continueRequestOrResponse(client, event);
...
// Handle the necessary events
});
Question: Can I do this at client.Fetch.enable() stage? E.g setup the the patterns filter so, it passes all requests (*) and rejects the service routes (started from https://service-domain-1.company.com and https://service-domain-2.company.com).
I have connected to my server as follows:
Socket socket = await Socket.connect('xxx', xxx)
But now I want to check if the socket is still connected. It would be even better if I have a listener that tells me when the connection is broken.
Thanks already!
Leonard
Listen to onDone in its stream
socket.stream.listen(
(dynamic message) {
debugPrint('message $message');
},
onDone: () {
debugPrint('socket closed');//if closed you will get it here
},
onError: (error) {
debugPrint('error $error');
},
);
When I try to connect to my nodejs server it is showing me this error-
connect_error: [{"cause":{"detailMessage":"Control frames must be final.","stackTrace":[],"suppressedExceptions":[]},"detailMessage":"websocket error","stackTrace":[],"suppressedExceptions":[]}]
I used flutter_socket_io for socket connection
My flutter code
socketIO = SocketIOManager().createSocketIO(
websocketUrl, '/', socketStatusCallback: (status) {
print("web socket -------------status");
print(status);
if (status.toString() == "connect") {
print("connected to server with websocket------------------------");
// socketIO.sendMessage("socket request", jsonEncode({"id": id}));
}
});
socketIO.init();
socketIO.connect().then((value){
print('socket connect');
});
I've created a web socket server with Node.js to connect two Flutter apps. I can post a message to server but when I listen to it on WebApp i receive an array [79,101] instead message (Oi). How can I solve it?
Sink Message
void _sendMessage(data) {
widget.channel.sink.add('Oi');
}
Cliente Stream Builder
StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
return Text(snapshot.hasData ? '${snapshot.data}' : 'Null');
},
)
Node.js Server
const WebSocket = require('ws');
// start the server and specify the port number
const port = 8080;
const wss = new WebSocket.Server({ port: port });
console.log(`[WebSocket] Starting WebSocket server on localhost:${port}`);
wss.on('connection', (ws, request) => {
const clientIp = request.sock.remoteAddress;
console.log(`[WebSocket] Client with IP ${clientIp} has connected`);
ws.send('Connected!');
// Broadcast aka send messages to all connected clients
ws.on('message', (message) => {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message); } })
console.log(`[WebSocket] Message ${message} was received`); });
});
This might not be the solution you are looking for but I would try and convert the response via String.fromCharCodesince the response might be ASCII characters to begin my way of debugging.
I have a super simple socket.io node server like below
// Socket!
io.on("connection", (socket) => {
console.log("a user connected");
socket.on("msg", (aaa) => {
console.log(aaa);
});
socket.on("fromServer", (_) => print(_));
console.log(socket.handshake.query)
});
And, here is my Flutter code to connect to the server
// Dart client
IO.Socket socket = IO.io(
'http://192.168.219.102:7199',
IO.OptionBuilder()
.setTransports(['polling'])
.disableAutoConnect()
.setQuery({"hee": 'asdf'})
.build());
socket.connect();
socket.onConnect((_) {
print(_);
});
On the network tab, I see two requests
101 HTTP 490ms
101 WS Pending
When I connect to the socket.io server from the other node.js server, I see the console.log of a user connected on the terminal. However, I see nothing from Flutter.
What can I do to receive the socket message on the server and connect the device.