dart-lang / web_socket_channel

StreamChannel wrappers for WebSockets.
https://pub.dev/packages/web_socket_channel
BSD 3-Clause "New" or "Revised" License
421 stars 109 forks source link

Websocket disconnects for no reason on flutter web #186

Open arualana opened 3 years ago

arualana commented 3 years ago

I reported the issue on flutter/flutter and they told me to come here https://github.com/flutter/flutter/issues/85146

This issue seems irrelevant to the flutter version as we went through several versions and the issue remains

We have a connection made with https://pub.dev/packages/web_socket_channel

We are sending the ping message within the interval required by the server

The connection lasts. sometimes 17 minutes, sometimes 7 hours, it varies, but eventually it disconnects,

This has been tested both on development build and production build in several devices.

Code is

_subscription = _channel!.stream.listen(
    (e) => _handlePusherEvent(e),
    onDone: () => _onDone(), // Clean disconnection here for no reason
    onError: (e) => _onWebsocketError(e),
);

void _onDone() {
  print("onDone");
}

The connection per se has no issue given that we are able to connect and send and receive messages while it is active.

Back end sends no errors whatsoever.

Thank you

[✓] Flutter (Channel master, 2.3.0-17.0.pre.416, on Linux Mint 20.1 5.4.0-58-generic, locale en_US.UTF-8) [✓] Chrome - develop for the web [✓] Android Studio (version 4.1) [✓] IntelliJ IDEA Ultimate Edition (version 2021.1) [✓] VS Code (version 1.56.2) [✓] Connected device (2 available)

grendes-wunder commented 3 years ago

@arualana : sorry for the side-note, but how do you send ping with a WebSocketChannel, if I may ask?

arualana commented 3 years ago

@grendes-wunder I am manually using a timer with Timer.periodic which I clear on disconnection. There is no built in function that I know of

grendes-wunder commented 3 years ago

@arualana : I see. Just to be clear: in this case you use first-class ws messages, and not low-level "ping" control-frames, right? https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2

(As far as I know, the proper way would be to use control-frames; furthermore these would not increase costs if you run WebSockets on AWS)

arualana commented 3 years ago

@grendes-wunder the message we need to send is not a string "ping", it is ajsonEncode({"event": pusher:ping",}) Frankly I don't know about low-level pings, it is the first time I am hearing of that. What does the implementation look like? I can't find any documentation

grendes-wunder commented 3 years ago

@arualana : I have linked the WebSocket reference above, ping is a "control-frame" with opcode of %x9

In case of IOSocketChannel, you can set a pingInterval, which in the very deep of the implementation uses this very opcode, as defined here: https://github.com/dart-lang/web_socket_channel/blob/master/lib/src/copy/web_socket_impl.dart#L47

JaxInfinitaz commented 7 months ago

WebSocket connection closed WS Channel CloseCode: null WS Channel CloseReason: null Error: WebSocketChannelException: WebSocket connection failed.

dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 330:10 createErrorWithStack dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 337:28 _throw dart-sdk/lib/core/errors.dart 120:5 throwWithStackTrace dart-sdk/lib/async/zone.dart 1386:11 callback dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7

I'm getting same issue exclusively on Web version with the above errors/logging. It disconnects immediately after connecting and authenticating with my websocket server but only when running from the web. Works fine on android, desktop, and iOS.

edit:

It only occurs when setting the 'protocols' field ie:

_channel = WebSocketChannel.connect(Uri.parse(wsUrl), protocols: { 'MQTT' } );