-
Notifications
You must be signed in to change notification settings - Fork 368
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Lack of ability to configure connection timeouts #1598
Comments
Any progress on this? 👀 |
What i was doing is create a native socket and wrap it in IOWebSocketChannel Like this WebSocket.connect(_SERVER_ADDRESS)
.timeout(Duration(seconds: 20))
.then((ws) {
try {
_channel = new IOWebSocketChannel(ws);
} catch (e) {
print(
'Error happened when opening a new websocket connection. ${e.toString()}');
} |
@kavinda1995 I got an error. The WebSocket that comes from connect is from |
@zeidReg - No. You must import WebSocket from dart:io. Not from any other package |
@kavinda1995 I don't really get it. I imported it from dart:io but when i press Ctrl + click on the class name i go to the file |
@ziedReg please provide your code snippet here. So we can elaborate 😃 |
These are the imports import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:web_socket_channel/html.dart';
import 'package:my_project/constants/variables.dart';
import 'package:web_socket_channel/io.dart'; this is the method where i connect to the socket void fetchImages() {
if (channel == null) {
// copying your code
WebSocket.connect("ws://"+settings.host+":"+settings.port.toString()).timeout(Duration(seconds: 5)).then((ws) {
try {
channel = new HtmlWebSocketChannel(ws); // there is an error at "ws"
} catch (e) {
print('Error happened when opening a new websocket connection. ${e.toString()}');
}
});
// what i'm working with right now
channel = HtmlWebSocketChannel.connect("ws://"+settings.host+":"+settings.port.toString());
}
channel.stream.listen((message) async{
bytes = base64Decode(message);
image = Image.memory(bytes);
await precacheImage(image.image, context);
setState(() {});
});
} The error is : The argument type 'WebSocket (where WebSocket is defined in ~/flutter/bin/cache/pkg/sky_engine/lib/_http/websocket.dart)' can't be assigned to the parameter type 'WebSocket (where WebSocket is defined in ~/flutter/bin/cache/pkg/sky_engine/lib/html/html_dart2js.dart)'. (argument_type_not_assignable at [my_project] lib/views/control/control.dart:44) I am using |
Oh 😞. Couldn't see any wrong in this |
@ziedReg I'm probably too late, but the issue here is that you are using HtmlWebSocketChannel (for web) while @kavinda1995 is using IOWebSocketChannel (for mobile). As noted, the WebSocket class in use is from the dart:io package, which cannot be used for web development. The two websocket implementations are not interchangeable. |
So there really isn't a good way to do this, particularly since the dart:html package only offers a constructor that doesn't return a future |
@kavinda1995 is your approach safe? 1- By running |
@sm2017 is correct. This can lead to resource leaks. The timeout passed to the It seems to me that a viable solution could be to pass a Currently, I believe the safest way to handle timeouts when establishing a web socket in Dart is to use an final r = Random();
final key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
final client = HttpClient();
client
.getUrl(Uri.parse(SERVER_ADDRESS))
.timeout(Duration(seconds: 20))
.then((request) {
request.headers.add('Connection', 'upgrade');
request.headers.add('Upgrade', 'websocket');
request.headers.add('sec-websocket-version', '13');
request.headers.add('sec-websocket-key', key);
request.close().then((response) {
response.detachSocket().then((socket) {
final webSocket = WebSocket.fromUpgradedSocket(socket, serverSide: false);
_channel = IOWebSocketChannel(webSocket);
});
});
}).catchError((error) {
// handle error
return null;
}); |
Thanks, works great! @theLee3 Any solution for Web though? |
@julien100000 For the web, we can simply check the status of the // WebSocket class from `html` library
final webSocket = WebSocket(SERVER_ADDRESS);
Future.delayed(Duration(seconds: 20), () {
if (webSocket.readyState == WebSocket.CONNECTING) {
webSocket.close();
// handle the timeout here
}
});
_channel = HtmlWebSocketChannel(webSocket); |
I think that I found not ideal but technically correct solution: final httpClient = HttpClient();
httpClient.connectionTimeout = Duration(seconds: 20);
final webSocket = await WebSocket.connect(
'some url',
customClient: httpClient,
);
final channel = IOWebSocketChannel(webSocket); |
@ycherniavskyi This is a good solution. I would also suggest setting |
This is a viable workaround, but |
Maybe something has changed since this was originally posted, but you can set a timeout like this: WebSocketChannel webSocket = WebSocketChannel.connect(Uri.parse(url));
await webSocket.ready.timeout(Duration(seconds: 10)); It then throws a |
On mobile connection quality can vary depending on the environment conditions.
if connection is bad for the moment sometimes connecting to a websocket servers can't be established now, and in this situation ConnectionTimeOut exception must thrown.
Actually this exception throws:
WebSocketChannelException: WebSocketChannelException: SocketException: OS Error: Connection timed out, errno = 110, address = 192.168.2.2, port = 56472
But it take around a 2min before happen.
This is too long for creating a realtime applications with websockets, and sometimes we need to fail faster.
Additionally, this 2 min behaviour is annoying because of issue #1610 that closed because issue #1614 and flutter/flutter#18204 created. (connecting and already connected states still not differentiable)
How this connection timeout can be configured in this package?
One year ago in issue #1611 nex3 answered me, that dart io implementation doesn't expose this API. But it is a superficial answer, because:
HttpClient has this property
https://api.dartlang.org/stable/2.4.0/dart-io/HttpClient/connectionTimeout.html
if we use dart.io or html implementation directly we can use
.timeout
function on futures:But when using this package I can't manipulate with connection timeout. If connection doesn't establish in acceptable time I can't fail gracefully.
The text was updated successfully, but these errors were encountered: