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