Code Monkey home page Code Monkey logo

Comments (10)

SteveAlexander avatar SteveAlexander commented on August 17, 2024 12

yes, my workaround is to create a WebSocket directly. Something like:

      final socket = await WebSocket
          .connect(url.toString())
          .timeout(_webSocketConnectionTimeout);
      return IOWebSocketChannel(socket);

Then I wrap this in a try-catch, so I can catch SocketException and TimeoutException and handle these in a way that makes sense for my app.

from web_socket_channel.

adityabansalx avatar adityabansalx commented on August 17, 2024 9

I was facing same issue
turned out, unhandled Socket execption was thrown during connect method.
not by the stream.

I believe IOWenSocketChannel would have similar approach to await and catch error

WebSocketChannel channel = WebSocketChannel.connect(uri );
  try {
    await channel.ready;
  } catch (e) {
   // handle exception here
   print("WebsocketChannel was unable to establishconnection");
  }

Stream stream = channel.stream;
    stream.listen((event) {
      print('Event from Stream: $event');
      
    },onError: (e){
      
    // handle stream error
    },
    onDone: (() {
     // stream on done callback... 
    }),
    cancelOnError: true
    );

from web_socket_channel.

markflarup avatar markflarup commented on August 17, 2024 2

I have the same problem, but I thought that the exception should be handled in socketClient.stream.listen( method), this method params receives an Error handler, so i decided put one like this:

socketClient.stream.listen(
	(message){
		// handling incoming messages
	},
	onError: //Here a put a Error handling function,
	onDone: function(){
		// communication has been closed 
	}
);

But nothing happends.

@roger357, the following way works for me:

      stream = widget.webSocketChannel.stream;
      streamSubscription = stream.listen(
          onData,
          onError: (error) {
             // method calls and what not here
          },
          cancelOnError: true);
    }

I don't know if it is working because I have a StreamSubscription or whether it simply is an additional step.

from web_socket_channel.

Jalmoud2 avatar Jalmoud2 commented on August 17, 2024 2

While @adityabansalx solution works, I find it weird that adding await channel.ready makes it catch the error. Can someone please explain this behavior? 🤔

from web_socket_channel.

adityabansalx avatar adityabansalx commented on August 17, 2024 2

@Jalmoud2, I think putting it this way, would help understand the behavior.

WebSocketChannel channel = WebSocketChannel.connect(Uri());

  channel.ready.then((_) {
    channel.stream.listen((event) {
      print('Event from Stream: $event');
     
    },onError: (e){
      
    // handle stream error
    },
    onDone: (() {
     // stream on done callback... 
    }),
    cancelOnError: true
    );

  }).onError((error, stackTrace) {
    print("WebsocketChannel was unable to establishconnection");
  });

from web_socket_channel.

sintrb avatar sintrb commented on August 17, 2024

Hi, did you found some solution?

from web_socket_channel.

sintrb avatar sintrb commented on August 17, 2024

I got it. Thanks.

from web_socket_channel.

rgr-dev avatar rgr-dev commented on August 17, 2024

I have the same problem, but I thought that the exception should be handled in socketClient.stream.listen( method), this method params receives an Error handler, so i decided put one like this:

socketClient.stream.listen(
	(message){
		// handling incoming messages
	},
	onError: //Here a put a Error handling function,
	onDone: function(){
		// communication has been closed 
	}
);

But nothing happends.

from web_socket_channel.

adityabansalx avatar adityabansalx commented on August 17, 2024

Hey @Jalmoud2, what I understood is, calling connect gives a channel immediately, and initiates the connection to the socket server which may fail. e.g. request timeout. compare it to async Http request.
You can await channel.ready to succeed before calling for a stream.
In the answer I have called stream even if channel fails, so stream calls onError if connection didnt succeed, this helps me put error handling in one place.. I guess its better to not do so..

The point is channel connection and stream are different things. you can get a Sink or a Stream from the channel and they can have errors during their own functioning

from web_socket_channel.

skillastat avatar skillastat commented on August 17, 2024

Thanks to you guys comments, I found what I was looking for and here it is:

  • in a try/catch block, await for channel.ready
  • if we good, we continue to another function that setups the channel.listen
  • otherwise, we try to reconnects. (In my case, I need to retry indefinitely, since my App relyes heavily on WebSockets.)
  • step 4 : ???
  • step 5 : 100% works all the time

EDIT: Added reconnect duration each time it failed, until a maximum of 60 seconds (import 'dart:math' as math;)... Reset the duration to 3 on connection succes.

// Flag to indicate whether a WebSocket connection attempt is currently in progress.
// This is used to prevent multiple simultaneous attempts to connect to the WebSocket, 
// which could lead to unexpected behavior or resource issues.

bool websocketConnecting = false;

// Reconnect duration starts at 3 seconds
int reconnectDuration = 3;

// This function is responsible for establishing a connection to a WebSocket server.
void connectWebsockets() async {

  // Check if a connection attempt is already in progress. If so, exit the function
  // early to prevent another concurrent attempt. This is important for maintaining
  // control over the connection process and avoiding unnecessary network traffic.
  
  if (websocketConnecting) {
    return; 
  }

  // Set the flag to true, indicating that a connection attempt is now underway.
  
  websocketConnecting = true;
  log("Attempting to connect to WebSocket");

  // Parse the WebSocket URL from a predefined constant. This URL is where the client
  // will attempt to establish the WebSocket connection.
  
  final wsUrl = Uri.parse(ApiConstants.WSOCKET);

  // Connect to the WebSocket server at the specified URL.
  // The pingInterval is set to send a "ping" message every 15 seconds to keep the 
  // connection alive and check its health. The connectTimeout is set to 20 seconds,
  // meaning the connection attempt will time out if not established within this duration.
  
  channel = IOWebSocketChannel.connect(
    wsUrl,
    pingInterval: Duration(seconds: 15),
    connectTimeout: Duration(seconds: 20)
  );

  try {
  
    // Await the ready property of the channel, which is a Future that completes when
    // the WebSocket connection is successfully established. This ensures that the 
    // following code only runs after a successful connection.
    
    await channel!.ready;
    print('WebSocket channel is ready');

    // Once the connection is established, set up the stream listeners to handle 
    // incoming messages, errors, and connection closures.
    
    setupWebSocketListeners();
    
  } catch (e) {
  
    // If an error occurs during the connection attempt or while waiting for the
    // connection to become ready, log the error and perform cleanup.
    
    print('WebSocket connection failed or stream error occurred: $e');

    // Set the channel to null to clean up and indicate that there is no active 
    // WebSocket connection.
    
    channel = null;

    // Reset the websocketConnecting flag to allow future connection attempts.
    
    websocketConnecting = false;

    // Retry connecting to the WebSocket. This creates resilience in the face of 
    // network issues or temporary server unavailability.
    
    Future.delayed(Duration(seconds: reconnectDuration), () {
      connectWebsockets();
      // Increment reconnectDuration by 3, up to a maximum of 60 seconds
      reconnectDuration = math.min(reconnectDuration + 3, 60);
      print("reconnectDuration: $reconnectDuration");
    });
    
  }
}

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.