Code Monkey home page Code Monkey logo

Comments (42)

dionjwa avatar dionjwa commented on August 17, 2024 88

This is needed to handle reconnects.

With this package I have no idea how to:

  1. Handle reconnects
  2. Know the state of the connection.

from web_socket_channel.

dionjwa avatar dionjwa commented on August 17, 2024 24

I don't understand how you're supposed to use a websocket package that is meant for mobile devices that has no way to handle disconnects (so you can reconnect). That's not something that you would ever expose in a production ready product. One disconnect because you go under a bridge, and that's it?

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024 23

The stream will emit a done event when the socket has disconnected--is that not enough?

from web_socket_channel.

faganchalabizada avatar faganchalabizada commented on August 17, 2024 18

2022 and there is no solid way yet ?!)

from web_socket_channel.

nailgilaziev avatar nailgilaziev commented on August 17, 2024 13

@nex3 , when server interface is going away stream didn't emit a done event! and this is a bug.

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024 12

@nailgilaziev that sounds like a bug with dart:io's implementation. I suggest finding a reproduction that just uses dart:io's WebSocket class and filing a bug against the dart-lang/sdk repo.

from web_socket_channel.

prijindal avatar prijindal commented on August 17, 2024 10

@Allan-Nava
I do something like this

WebSocket socket;

void _onDisconnected() {
  print('Disconnected');
  if (socket != null) {
    socket.close();
  }
  socket = null;
  _tryConnect();
}

void _tryConnect() { 
  WebSocket.connect(url).then((ws) {
    socekt = ws;
    socket.listen(
      (dynamic message) {
        print(message)
      },
      onDone: _onDisconnected,
      onError: (dynamic error) => _onDisconnected(),
    );
    socket.done.then((dynamic _) => _onDisconnected());
  });
}  

from web_socket_channel.

angel1st avatar angel1st commented on August 17, 2024 5

Any recent updates on this request? It is something really required in case you are going after mobile app on production - see #40 as well...

from web_socket_channel.

ignertic avatar ignertic commented on August 17, 2024 5

@Allan-Nava; wrap connection initialization in a function and call it every time the onDone event is triggered

from web_socket_channel.

isinghmitesh avatar isinghmitesh commented on August 17, 2024 2

Hi everyone, I got a workaround. And it works (Did not test is very hard).
I am using flutter package: https://pub.dev/packages/connectivity

So with this package, I can listen to connection state changes like this :

StreamSubscription<ConnectivityResult> _connectivitySubscription;
_connectivitySubscription = Connectivity()
       .onConnectivityChanged.listen((ConnectivityResult result) {
      if (result == ConnectivityResult.wifi ||
          result == ConnectivityResult.mobile) {
        _tryConnect();
      }
    });

and then as above mentioned _tryConnect Function :

void _tryConnect() {
    final channel = IOWebSocketChannel.connect(
        "url");
    channel.sink.add("connected");
    channel.stream.listen(
      (message) {
        print(message);
      },
      onError: (dynamic error) => print(error),
    );
  }

In this way, if connection drops then the _connectivitySubscription will change to none and when back online which will result in wifi or mobile. it will call _tryConnect() and connect. Open to suggestions. (Peace)

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024 2

Sorry, I'm no longer on the Dart team and no longer a maintainer of this package.

from web_socket_channel.

gauravmehta13 avatar gauravmehta13 commented on August 17, 2024 2

2024 and there is no solid way yet ?!)

from web_socket_channel.

sgon00 avatar sgon00 commented on August 17, 2024 1

Hi, I am new to websocket and there are really not much flutter websocket articles online. Can anyone please show me how to do reconnection in flutter when the connection is lost somehow (for example, the server machine restarts). When I search the keywords flutter websocket reconnect, I find nothing related in google except this issue. Thank you very much.

from web_socket_channel.

flukejones avatar flukejones commented on August 17, 2024 1

@Allan-Nava
I do something like this

WebSocket socket;

void _onDisconnected() {
  print('Disconnected');
  if (socket != null) {
    socket.close();
  }
  socket = null;
  _tryConnect();
}

void _tryConnect() { 
  WebSocket.connect(url).then((ws) {
    socekt = ws;
    socket.listen(
      (dynamic message) {
        print(message)
      },
      onDone: _onDisconnected,
      onError: (dynamic error) => _onDisconnected(),
    );
    socket.done.then((dynamic _) => _onDisconnected());
  });
}  

I've recently tried doing something similar. My situation is a little different though - I need to know when a particular machine is turned off, in this case there does not seem to be anything emitted in any particular way (neither the socket or the stream emit onDone or onError) until I turn the machine back on, then the connection is reset and errors happen.

I need to know if the TCP socket is still live without sending a command over the socket to get the machine to respond.

from web_socket_channel.

monolidth avatar monolidth commented on August 17, 2024 1

@hogdamian You can implement auto reconnect by modifying the code of @Lyuzonggui slightly because the send method call initCommunication() method, this would mostly fail if the send method is invoked frequently causing a lot of socket recreations.

import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/io.dart';

WebSocketsHandler sockets = new WebSocketsHandler();

const String _SERVER_ADDRESS = "ws://127.0.0.1:6800/jsonrpc";

class WebSocketsHandler {
  static final WebSocketsHandler _sockets = new WebSocketsHandler._internal();

  factory WebSocketsHandler() => _sockets;

  WebSocketsHandler._internal();

  IOWebSocketChannel _channel;
  
  bool _disconnected = true;
  
  int _times = 0;

  ObserverList<Function> _listeners = new ObserverList<Function>();

  initCommunication() async {
    reset();
    try {
      _times += 1;
      debugPrint("try to connect $_times time(s)");
      _channel = new IOWebSocketChannel.connect(_SERVER_ADDRESS);
      _disconnected = false;
      _channel.stream.listen(
      _onReceptionOfMessage,
      onError:(error) {/* debugPrint(error); */},
     onDone: () {
        debugPrint("Receive done event.");
        _disconnected = true;
       // add delay here
        Future.delayed(const Duration(seconds: 1))
            .then((value) => initCommunication());
      });
    } catch (e) {/** */}
  }

  reset() {
    if (_channel != null) {
      if (_channel.sink != null) {
        _channel.sink.close();
        _disconnected = true;
      }
    }
  }

  List<String> failedKeys = [];
  send(String message) {
    ///check connection before send message
    if (_disconnected) {
      // add to list here 
     failedKeys.add(message);
    }
    if (_channel != null) {
      if (_channel.sink != null && _disconnected == false) {
        _channel.sink.add(message);
      }
      // add them later
    }
  }

  addListener(Function callback) {
    _listeners.add(callback);
  }

  removeListener(Function callback) {
    _listeners.remove(callback);
  }

  _onReceptionOfMessage(message) {
    _disconnected = false;
    _listeners.forEach((Function callback) {
      callback(message);
    });
  }
}

And create a timer that will fetch the missing keys:

Timer.periodic(const Duration(seconds: 5), (timer) {
      if (failedKeys.isEmpty) return;
      if (kDebugMode) print("Update failed key ${failedKeys.length}");
      for (var entry in failedKeys) {
        channel!.sink.add(entry.websocketData);
      }

Just call the initCommunication method in the main.dart method.

Regards,

William

from web_socket_channel.

Bungeefan avatar Bungeefan commented on August 17, 2024 1

@nex3 Are there any plans to ever implement the readyState?
It is clearly stated that several people would need this, and I couldn't identify any problem which would block this from being implemented.

Would a pull request help?

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024

What do you mean by "the state", exactly?

from web_socket_channel.

gradddev avatar gradddev commented on August 17, 2024

https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants

from web_socket_channel.

gradddev avatar gradddev commented on August 17, 2024

An event is also needed for each state.

from web_socket_channel.

gradddev avatar gradddev commented on August 17, 2024

@dionjwa What package do you use now?

from web_socket_channel.

dionjwa avatar dionjwa commented on August 17, 2024

@AlexeySemigradsky This is my first foray into using flutter. I want to write a cross-platform app, where the core requirement is a persistent websocket connection. It doesn't look like flutter is ready to support this as yet.

from web_socket_channel.

gradddev avatar gradddev commented on August 17, 2024

@nex3 So what about this feature? Should I wait for its implementation?

from web_socket_channel.

gradddev avatar gradddev commented on August 17, 2024

I started working on the Socket.IO plugin for the Flutter instead of using web_socket_channel.

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024

Because WebSocketChannel needs to work on both the Dart VM and in the browser, the best we can do is expose the subset of APIs supported on both platforms. We can (and probably should) expose a readyState getter, but because dart:io's WebSocket class doesn't provide any events when that state changes there's no way for this package to support them either.

from web_socket_channel.

dionjwa avatar dionjwa commented on August 17, 2024

@nex3 Somehow that wasn't clear. Yes, that would definitely be sufficient. Thank you!

from web_socket_channel.

nailgilaziev avatar nailgilaziev commented on August 17, 2024

I think that is a lib bug(lack of implementation), because I rewrite my code to use pure dart:io
If I use this

done → Future
Return a future which is completed when the StreamSink is finished.

read-only, inherited

https://api.dartlang.org/stable/1.24.3/dart-io/WebSocket-class.html

then error event exist

from web_socket_channel.

nex3 avatar nex3 commented on August 17, 2024

Can you produce a minimal reproduction, including server code, where dart:io emits a done event but this package does not?

from web_socket_channel.

nailgilaziev avatar nailgilaziev commented on August 17, 2024

My server code running on kotlin - ktor. repo But is does not matter. You can use public ehho server. ws://echo.websocket.org
What matter is that you need emulate bad network condition. For this I use Network Link Conditioner with 100% loss profile.

Full code listings:

  1. channel_example code
  2. dart io example code

channel_example code is a tutorial example code from cookbook but with two difference:

  1. added pingInterval to connect method pingInterval: Duration(seconds: 10)
  2. print lines for debugging in StreamBuilder

dart io example code contains with handy reconnect functionality and other debug stuffs, but main thing is next:

ws.done.then((v) {
          setState(() {
            ex = new Exception("Connection is done with v=$v");
            timeprint("DONE");
          });
        });

This lambda called when connection is down. Not a lambda for onDone parameter for `ws.listen()' function.

What the behaviour when we see the difference between channel package and dart:io code:

  1. Firstly, we connected to ws server and try to send and receive messages - both works fine.
  2. Then we switch on Network Link Conditioner tool with 100% loss profile.
  3. wait

And here the difference come. Because we specife in both code that we use pingInterval after around 20sec dart:io code call done lambda. But channel example don't call anything, no matter how you wait.

from web_socket_channel.

 avatar commented on August 17, 2024

In my case, I do not receive 'onDone' message or anything for that matter if the mobile loses data connection. Will it be possible for me to ask the IOWebSocketChannel if it is still connected every 5 seconds or so? I imagine it will know if it is following WebSocket protocol because it won't be receiving frames. Thanks!

from web_socket_channel.

Allan-Nava avatar Allan-Nava commented on August 17, 2024

Is possible to reconnect after the websocket is die?

from web_socket_channel.

Allan-Nava avatar Allan-Nava commented on August 17, 2024

@Allan-Nava; wrap connection initialization in a function and call it every time the onDone event is triggered

Can you please give me an example, thanks ❤️

from web_socket_channel.

Allan-Nava avatar Allan-Nava commented on August 17, 2024

@Allan-Nava
I do something like this

WebSocket socket;

void _onDisconnected() {
  print('Disconnected');
  if (socket != null) {
    socket.close();
  }
  socket = null;
  _tryConnect();
}

void _tryConnect() { 
  WebSocket.connect(url).then((ws) {
    socekt = ws;
    socket.listen(
      (dynamic message) {
        print(message)
      },
      onDone: _onDisconnected,
      onError: (dynamic error) => _onDisconnected(),
    );
    socket.done.then((dynamic _) => _onDisconnected());
  });
}  

Thanks

from web_socket_channel.

pyzenberg avatar pyzenberg commented on August 17, 2024

I'm using this solution and works for me.
https://gist.github.com/pyzenberg/4037e11627a8cac1c442183cc7cf172a

from web_socket_channel.

konsultaner avatar konsultaner commented on August 17, 2024

Any news on this? I implemented a WebSocket sub protocol (WAMP) with dart (+flutter) and it seems impossible to handle reconnects in a nice way. I'll end up to hack something in combination with custom Ping/Pongs and Bad state: No element errors to make this work with WebSockets:io and Sockets:io.

WebSockets:html works as expected as this is the browser implementation.

The issues I experience (so far) are:

  • server closed connection, but all socket client states are connected, the stream is not closing either
  • pingInterval in WebSockets:io does weired things - The server just does not receive anything
    • await WebSocket.connect(_url, protocols: [_serializerType]) -> runs forever
  • I would love to set SO_KEEPALIVE in Socket, I have no Idea how to?

from web_socket_channel.

isco-msyv avatar isco-msyv commented on August 17, 2024

Can be helpful: https://stackoverflow.com/questions/55503083/flutter-websockets-autoreconnect-how-to-implement/62095514#62095514

from web_socket_channel.

Atomos-X avatar Atomos-X commented on August 17, 2024

I make GUI app for aria2, same problem, when I read this:
https://www.didierboelens.com/2018/06/web-sockets-build-a-real-time-game/

so my way is, Singleton handler, check connection befor send message.it works fine

import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/io.dart';

WebSocketsHandler sockets = new WebSocketsHandler();

const String _SERVER_ADDRESS = "ws://127.0.0.1:6800/jsonrpc";

class WebSocketsHandler {
  static final WebSocketsHandler _sockets = new WebSocketsHandler._internal();

  factory WebSocketsHandler() => _sockets;

  WebSocketsHandler._internal();

  IOWebSocketChannel _channel;
  
  bool _disconnected = true;
  
  int _times = 0;

  ObserverList<Function> _listeners = new ObserverList<Function>();

  initCommunication() async {
    reset();
    try {
      _times += 1;
      debugPrint("try to connect $_times time(s)");
      _channel = new IOWebSocketChannel.connect(_SERVER_ADDRESS);
      _disconnected = false;
      _channel.stream.listen(
      _onReceptionOfMessage,
      onError:(error) {/* debugPrint(error); */},
      onDone:(){_disconnected = true;});
    } catch (e) {/** */}
  }

  reset() {
    if (_channel != null) {
      if (_channel.sink != null) {
        _channel.sink.close();
        _disconnected = true;
      }
    }
  }

  send(String message) {
    ///check connection before send message
    if (_disconnected) {
      initCommunication();
    }
    if (_channel != null) {
      if (_channel.sink != null && _disconnected == false) {
        _channel.sink.add(message);
      }
    }
  }

  addListener(Function callback) {
    _listeners.add(callback);
  }

  removeListener(Function callback) {
    _listeners.remove(callback);
  }

  _onReceptionOfMessage(message) {
    _disconnected = false;
    _listeners.forEach((Function callback) {
      callback(message);
    });
  }
}

from web_socket_channel.

konsultaner avatar konsultaner commented on August 17, 2024

People could use the WAMP protocol with my dart client to work with web sockets / sockets to deliver messages. I have implemented all that is needed to handle the states.

from web_socket_channel.

ingmferrer avatar ingmferrer commented on August 17, 2024

My clients randomly disconnects and i need to find a solution for this.

from web_socket_channel.

jdeltoft avatar jdeltoft commented on August 17, 2024

@Lyuzonggui I'm not sure I follow. I'm using websockets with flutter web, and it works. But I'm seeing the connection drop I think some times if I close my laptop or minimize chrome. Haven't really characterized fully. But I would love a way to check if the stream is there in the flutter web periodically and reconnect if down. I see your reset() function but I don't see any way this checks if it's down?

  reset() {
    if (_channel != null) {
      if (_channel.sink != null) {
        _channel.sink.close();
        _disconnected = true;
      }
    }
  }

Is checking for sink being null maybe a check for a connection being gone?

from web_socket_channel.

konsultaner avatar konsultaner commented on August 17, 2024

2022 and there is no solid way yet ?!)

@faganchalabizada seems like this is of very low priority. I guess the problem here is to implement this for all plattforms

from web_socket_channel.

hogdamian avatar hogdamian commented on August 17, 2024

I am still having the same issue.
catching the connect function is not working.
I want to catch the error.
For example "Connection failed"

from web_socket_channel.

danaodai951 avatar danaodai951 commented on August 17, 2024

IOWebSocketChannel - innerWebSocket - readyState

/// Possible states of the connection.
static const int connecting = 0;
static const int open = 1;
static const int closing = 2;
static const int closed = 3;

from web_socket_channel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.