How to check if the tcp socket is still connected in Flutter? - flutter

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');
},
);

Related

Flutter not able connect to websocket

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');
});

How to handle websocket with dart:io Flutter

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();
}

Flutter SocketIo Client TimeOut

I'm trying to add socket io to a flutter project. I'm using socket_io_client 2.0.0-beta.4-nullsafety.0 but when I try to connect to server's socket it just refuse the connection and throw a timeout error.
Here's the code im using:
_connectSocket() {
Socket socket = io('SERVER IP',
OptionBuilder()
.enableAutoConnect()
.build()
);
socket.onConnecting((data) => print("conecting socket..."));
socket.onConnectError((data) => print("error : "+data.toString()));
socket.onConnectTimeout((data) => print(data.toString()));
}
Has anyone been through this?
Thanks in advance
socket = IO.io("ip sever",<String, dynamic>{
"transports": ["websocket"],
"autoConnect": false,
'extraHeaders': {'foo': 'bar'},
}); socket.connect();
// socket = await IO.io('ip server',
// OptionBuilder()
// .setTransports(['websocket']).build());
socket.onConnect((_) => print('connect'));
socket.onConnect((_) {
print('connect');
});
socket.onConnectError((data) => print( 'error : '+ data.toString() ));

How can I connect WebSocket listening to one port to Net socket listening to another, using NodeJS?

This is the approach I tried but not working. I can forward the incoming messages from the WebSocket connection to the NetSocket, but only the first one received by NetSocket arrives to the client behind the WebSocket.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const NetSocket = require('net');
const net = new NetSocket.Socket();
// Web socket
wss.on('connection', function connection(ws) {
console.log((new Date()) + ' Remote connection accepted ' + ws.remoteAddress);
ws.on('message', function incoming(message) {
console.log('Received from remote: %s', message);
net.write(message)
});
ws.on('close', function(){
console.log((new Date()) + ' Remote connection closed');
});
});
// Net socket
net.connect(8745, '127.0.0.1', function() {
console.log((new Date()) + ' Local connection accepted');
});
net.on('data', function(data) {
console.log('Received from local: ' + data);
// Iterate the connected devices to send the broadcast
wss.clients.forEach(function each(c) {
if (c.readyState === WebSocket.OPEN) {
c.send(data);
}
});
});
net.on('close', function() {
console.log('Local connection closed');
});
After a new research I noticed that the problem was in my swift code.
private func setReceiveHandler() {
webSocketTask.receive { result in
defer { self.setReceiveHandler() } // I was missing this line
do {
let message = try result.get()
switch message {
case let .string(text):
print("Received text message: \(text)")
case let .data(data):
So, just adding defer { self.setReceiveHandler() } to my function, it started to work.
Note the defer statement at the start of the receive handler. It calls self.setReceiveHandler() to reset the receive handler on the socket connection to allow it to receive the next message. Currently, the receive handler you set on a socket connection is only called once, rather than every time a message is received. By using a defer statement, you make sure that self.setReceiveHandler is always called before exiting the scope of the receive handler, which makes sure that you always receive the next message from your socket connection.
I've got the information from:
https://www.donnywals.com/real-time-data-exchange-using-web-sockets-in-ios-13/

How to know my socket connect is success or not?

I want to do something when the nodejs server is started or I will do something else not related to the server.
But how could I know that. There is no property that shows the status of the connection, and because the socket is asynchronous that I can't get the err by try..catch...
The following is my clinet code.
var socket = io.connect('http://localhost:3000/monitor');
socket.on('message', function (data) {
console.log(data);
});
Anyone can tell me how to if(is connected).. else.. in this place?
Try listening to the following events:
socket.on( 'connect', function() {
});
socket.on( 'disconnect', function() {
});
socket.on( 'connect_failed', function() {
});
socket.on( 'error', function() {
});
Socket.io has some bugs in firing some events so it's better to listen to all of those that might mean a connection failed.