Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flutter websockets autoreconnect - how to implement

I am struggling how to implement websockets autoreconnect in flutter. I use web_socket_channel, however, the plugin just wraps dart.io WebSocket, hence any solution based on WebSocket class will work for me as well.

I already figured out, how to catch the socket disconnection, see the code snippet below:

    try {
      _channel = IOWebSocketChannel.connect(
        wsUrl,
      );

      ///
      /// Start listening to new notifications / messages
      ///
      _channel.stream.listen(
        _onMessageFromServer,
        onDone: () {
          debugPrint('ws channel closed');
        },
        onError: (error) {
          debugPrint('ws error $error');
        },
      );
    } catch (e) {
      ///
      /// General error handling
      /// TODO handle connection failure
      ///
      debugPrint('Connection exception $e');
    }

I was thinking to call IOWebSocketChannel.connect from within onDone, however, this leads to a kind of infinite loop - since I have to close the _channel prior calling connect again, this on its turn calls onDone again and so on.

Any help would be greatly appreciated!

like image 280
Angel Todorov Avatar asked Apr 03 '19 19:04

Angel Todorov


People also ask

How do you implement WebSockets?

webSockets are implemented as follows: Client makes HTTP request to server with "upgrade" header on the request. If server agrees to the upgrade, then client and server exchange some security credentials and the protocol on the existing TCP socket is switched from HTTP to webSocket.

How do I send a WebSocket message?

To send a message through the WebSocket connection you call the send() method on your WebSocket instance; passing in the data you want to transfer. socket. send(data); You can send both text and binary data through a WebSocket.

How do I connect to a WebSocket server in flutter?

Connect to a WebSocket server The web_socket_channel package provides the tools you need to connect to a WebSocket server. The package provides a WebSocketChannel that allows you to both listen for messages from the server and push messages to the server. In Flutter, use the following line to create a WebSocketChannel that connects to a server:

What is the WebSocket API and how does it work?

What is the WebSocket API? According to Mozilla, the WebSocket API is “an advanced technology that makes it possible to open a two-way interactive communication session between the user’s browser and a server… you can send messages to a server and receive event-driven responses without having to poll the server for a reply.”

How do I connect to a server using WebSockets?

Connect to a WebSocket server 2. Listen for messages from the server 3. Send data to the server 4. Close the WebSocket connection In addition to normal HTTP requests, you can connect to servers using WebSockets . WebSockets allow for two-way communication with a server without polling.

How to use streambuilder in flutter?

The StreamBuilder widget connects to a Stream and asks Flutter to rebuild every time it receives an event using the given builder () function. 3. Send data to the server


1 Answers

With the package:web_socket_channel (IOWebSocketChannel) there is not any way in order to implement reconnection for the socket connections. But you can use WebSocket class in order to implement a reconnectable connection.

You can implement the WebSocket channel and then broadcast messages with StreamController class. Working example:

import 'dart:async';
import 'dart:io';

class NotificationController {

  static final NotificationController _singleton = new NotificationController._internal();

  StreamController<String> streamController = new StreamController.broadcast(sync: true);

  String wsUrl = 'ws://YOUR_WEBSERVICE_URL';

  WebSocket channel;

  factory NotificationController() {
    return _singleton;
  }

  NotificationController._internal() {
    initWebSocketConnection();
  }

  initWebSocketConnection() async {
    print("conecting...");
    this.channel = await connectWs();
    print("socket connection initializied");
    this.channel.done.then((dynamic _) => _onDisconnected());
    broadcastNotifications();
  }

  broadcastNotifications() {
    this.channel.listen((streamData) {
      streamController.add(streamData);
    }, onDone: () {
      print("conecting aborted");
      initWebSocketConnection();
    }, onError: (e) {
      print('Server error: $e');
      initWebSocketConnection();
    });
  }

  connectWs() async{
    try {
      return await WebSocket.connect(wsUrl);
    } catch  (e) {
      print("Error! can not connect WS connectWs " + e.toString());
      await Future.delayed(Duration(milliseconds: 10000));
      return await connectWs();
    }

  }

  void _onDisconnected() {
    initWebSocketConnection();
  }
}

Because the notification controller returns a singleton instance, then there will be always one Socket connection between the server and device. And with the broadcast method of StreamController, we can share the data sent by Websocket between multiple consumers

var _streamController = new NotificationController().streamController;

_streamController.stream.listen(pushNotifications);
like image 156
Isco msyv Avatar answered Sep 17 '22 12:09

Isco msyv