Code Monkey home page Code Monkey logo

Comments (17)

MarcelGarus avatar MarcelGarus commented on August 17, 2024 21

Any progress on this? πŸ‘€

from web_socket_channel.

ycherniavskyi avatar ycherniavskyi commented on August 17, 2024 8

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);

from web_socket_channel.

kavinda1995 avatar kavinda1995 commented on August 17, 2024 4

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()}');
      }

from web_socket_channel.

theLee3 avatar theLee3 commented on August 17, 2024 4

@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.

from web_socket_channel.

theLee3 avatar theLee3 commented on August 17, 2024 4

@sm2017 is correct. This can lead to resource leaks. The timeout passed to the WebSocket is for the communication Stream, not the establishment of the WebSocket.

It seems to me that a viable solution could be to pass a connectionTimeout parameter to the WebSocket constructor which would be passed on to the HttpClient when establishing a connection. This could also trickle up to IOWebSocketChannel.connect making establishing web sockets much easier/safer. Unless there is a reason unbeknown to me why this is should not be.

Currently, I believe the safest way to handle timeouts when establishing a web socket in Dart is to use an HttpClient and manually upgrade to a WebSocket. Then you can create the IOWebSocketChannel with the WebSocket.

    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;
         });

from web_socket_channel.

sm2017 avatar sm2017 commented on August 17, 2024 3

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 is your approach safe?
Consider the following scenario:

1- By running WebSocket.connect a web socket connection will be established but due to network issues, it can be established after 30 seconds
2- timeout(Duration(seconds: 20)) will completeError the feature with TimeoutException after 20 seconds
3- We have a reconnect logic in our code in the catch and do same thing for connection
4- By running WebSocket.connect again, a new web socket connection will be established without timeout
5- after 30 seconds, the first connection is established, So we have 2 web socked connection, and there is no way to close the first

from web_socket_channel.

theLee3 avatar theLee3 commented on August 17, 2024 2

@ycherniavskyi This is a good solution. I would also suggest setting httpClient.idleTimeout and/or webSocket.pingInterval according to your needs.

from web_socket_channel.

ziedReg avatar ziedReg commented on August 17, 2024

@kavinda1995 I got an error. The WebSocket that comes from connect is from flutter/bin/cache/pkg/sky_engine/lib/_http/websocket.dart while the IOWebSocketChannel requires a WebSocket from flutter/bin/cache/pkg/sky_engine/lib/html/html_dart2js.dart.

from web_socket_channel.

kavinda1995 avatar kavinda1995 commented on August 17, 2024

@zeidReg - No. You must import WebSocket from dart:io. Not from any other package

from web_socket_channel.

ziedReg avatar ziedReg commented on August 17, 2024

@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 flutter/bin/cache/pkg/sky_engine/lib/_http/websocket.dart

from web_socket_channel.

kavinda1995 avatar kavinda1995 commented on August 17, 2024

@ziedReg please provide your code snippet here. So we can elaborate πŸ˜ƒ

from web_socket_channel.

ziedReg avatar ziedReg commented on August 17, 2024

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 HtmlWebSocketChannel because i'm working on web but i tried IOWebSocketChannel and got the same error

from web_socket_channel.

kavinda1995 avatar kavinda1995 commented on August 17, 2024

Oh 😞. Couldn't see any wrong in this

from web_socket_channel.

steeling avatar steeling commented on August 17, 2024

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

from web_socket_channel.

julienduchow avatar julienduchow commented on August 17, 2024

Thanks, works great! @theLee3 Any solution for Web though?

from web_socket_channel.

theLee3 avatar theLee3 commented on August 17, 2024

@julien100000 For the web, we can simply check the status of the WebSocket after the desired timeout period, and if the connection has not been established, close the socket and handle the timeout according to your needs.

    // 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);

from web_socket_channel.

Tienisto avatar Tienisto commented on August 17, 2024

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);

This is a viable workaround, but dart:io is not allowed in web

from web_socket_channel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.