颤振websockets自动重新连接-如何实现

颤振websockets自动重新连接-如何实现,websocket,flutter,dart-io,Websocket,Flutter,Dart Io,我正在努力实现颤振中的websocketsautoreconnect。然而,我使用的插件只是包装,因此任何基于WebSocket类的解决方案也适用于我 我已经了解了如何捕获套接字断开连接,请参见下面的代码片段: try { _channel = IOWebSocketChannel.connect( wsUrl, ); /// /// Start listening to new notifications / messa

我正在努力实现颤振中的
websockets
autoreconnect。然而,我使用的插件只是包装,因此任何基于
WebSocket
类的解决方案也适用于我

我已经了解了如何捕获套接字断开连接,请参见下面的代码片段:

    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');
    }
我想从
onDone
内部调用
IOWebSocketChannel.connect
,但是,这会导致一种无限循环-因为我必须在再次调用
connect
之前关闭
\u频道,所以它会再次调用
onDone
,以此类推

任何帮助都将不胜感激

以下是我的工作:

void reconnect() {
    setState(() {
      _channel = IOWebSocketChannel.connect(wsUrl);
    });
    _channel.stream.listen((data) => processMessage(data), onDone: reconnect);
  }
然后,要启动websocket,只需对reconnect()进行初始调用。基本上,这是在调用onDone回调时重新创建WebSocket,这是在连接被破坏时发生的。所以,连接被破坏了——好吧,让我们自动重新连接。我还没有找到一种不重新创建频道的方法。理想情况下,会有一个可以重新连接到现有URL的_channel.connect(),或者某种自动重新连接功能,但这似乎不存在

哦,这里有一个更好的方法,可以在远程服务器关闭时消除难看的重新连接异常回溯,并增加4秒的重新连接延迟。在这种情况下,cancelOnError参数会在出现任何错误时触发套接字关闭

  wserror(err) async {
    print(new DateTime.now().toString() + " Connection error: $err");
    await reconnect();
  }

 reconnect() async {
    if (_channel != null) {
      // add in a reconnect delay
      await Future.delayed(Duration(seconds: 4));
    }
    setState(() {
      print(new DateTime.now().toString() + " Starting connection attempt...");
      _channel = IOWebSocketChannel.connect(wsUrl);
      print(new DateTime.now().toString() + " Connection attempt completed.");
    });
    _channel.stream.listen((data) => processMessage(data), onDone: reconnect, onError: wserror, cancelOnError: true);
  }

对于包:web_socket_channel(IOWebSocketChannel),没有任何方法来实现套接字连接的重新连接。但您可以使用WebSocket类来实现可重新连接的连接

您可以实现WebSocket频道,然后使用StreamController类广播消息。工作示例:

导入'dart:async';
导入“dart:io”;
类通知控制器{
静态最终通知控制器_singleton=新通知控制器。_internal();
StreamController StreamController=新的StreamController.broadcast(同步:true);
字符串wsUrl='ws://YOUR\u WEBSERVICE\u URL';
网箱通道;
工厂通知控制器(){
返回单件;
}
通知控制器。_内部(){
initWebSocketConnection();
}
initWebSocketConnection()异步{
打印(“连接…”);
this.channel=wait connectWs();
打印(“插座连接初始化”);
this.channel.done.then((dynamic=undisconnected());
广播通知();
}
广播通知(){
this.channel.listen((streamData){
streamController.add(streamData);
},onDone:(){
打印(“连接中止”);
initWebSocketConnection();
},onError:(e){
打印('Server error:$e');
initWebSocketConnection();
});
}
connectWs()异步{
试一试{
返回wait wait WebSocket.connect(wsUrl);
}捕获(e){
打印(“错误!无法连接WS-connectWs”+e.toString());
等待未来。延迟(持续时间(毫秒:10000));
return wait connectWs();
}
}
void _onDisconnected(){
initWebSocketConnection();
}
}
因为通知控制器返回一个单例实例,所以服务器和设备之间总是有一个套接字连接。通过StreamController的广播方式,我们可以在多个用户之间共享Websocket发送的数据

var\u streamController=new NotificationController().streamController;
_streamController.stream.listen(推送通知);

我不直接使用connect()方法返回的通道,我使用委派的StreamController从ws通道的流转发数据:

StreamController<dynamic> delegatedCtrl = StreamController<String>();

Stream<int>void  IOWebSocketChannel.connect(endpoint).stream.listen((event) {
    ctrl.add(event);
  }, onError: (e) async {
    await Future.delayed(Duration(seconds: 3));
    connect(ctrl, endpoint);
  }, onDone: () async {
    await Future.delayed(Duration(seconds: 3));
    connect(ctrl, endpoint);
  }, cancelOnError: true);
}

我使用的是socket.io,重新连接由插件自动处理。任何原因都必须使用websocket?
socket.io与
websocket
相比开销太大。不过,我正在考虑将
socket.io
作为备份计划。您使用的是哪个特定的
socket.io
包?adhara_socket_ioI已经创建了另一个线程来运行计时器,该计时器每10秒向服务器发送一次心跳信号。此计时器功能还具有打印(“HB”);陈述即使在应用程序进入后台并关闭屏幕后,计时器也可以24/7运行(即控制台查看不间断的“HB”24/7),但是,在关闭屏幕后大约10分钟,心跳停止发送。websocket能在这种情况下生存吗?那么,毕竟您创建了一个hb来保持套接字的生存?根据我在javascript客户端(浏览器和移动网络视图)中使用socket.io的经验,我不需要创建类似的东西——socket.io自己处理这个问题。我很惊讶地了解到,在弗利特,情况并非如此。我相信您描述的上述方法也应该适用于websocket。在后台模式下重新停止一段时间-这是由于操作系统电池优化模式,您很难克服它。唯一可行的解决方案是,一旦你的应用程序回到前台模式,就重新连接。因此,从本质上说,你最终也得到了(不是吗:-)澄清问题:
WebSocket.channel.done
IOWebSocketChannel
流的
onDone
onError
有什么不同?
StreamBuilder(
  stream: delegatedCtrl.stream,
  builder: (context, snapshot) {
    return Text(snapshot.hasData ? '${snapshot.data}' : '');
  },
)