Marfusios / websocket-client

đŸ”§ .NET/C# websocket client library
MIT License
682 stars 126 forks source link

Ensure all messages are sent before disconnection #111

Closed zeroed-tech closed 2 years ago

zeroed-tech commented 2 years ago

Appologies if this has already been answered but I couldnt see it in a previous issue.

Is there away to track how many messages have been queued up to be sent? I'm doing something like this (exception handling removed to keep it small):

using (IWebsocketClient client = new WebsocketClient(new Uri("ws://127.0.0.1:8080/ws")))
{
    await client.StartOrFail();

    while (!processingQueue.IsCompleted)
    {
        T currentTask = processingQueue.Take();
        client.Send(JsonConvert.SerializeObject(currentTask));
    }

    await client.Stop(WebSocketCloseStatus.NormalClosure, "Shutting down");
}

So this should establish a connection, perform some processing on each event in the queue and send the result over the socket then close the connection.

The problem is, the connection gets closed before any data can be sent however if i put a sleep just before the call to Stop, all data hits the server.

Obviously sleeping for a random amount of time before closing the connection is not a great solution as network latency and the amount of data that needs to be transmitted may cause the sleep to expire before all data has been transmitted.

So is there a way to determine if all data has been transmitted before stopping the connection?

Thanks

Marfusios commented 2 years ago

Hey @zeroed-tech, good idea, there is no such feature yet, could be a nice PR.

You can use the method await SendInstant() as a temporary workaround. So you will be sure all messages were sent.

zeroed-tech commented 2 years ago

Thanks @Marfusios, I'll see what I can come up with and do a PR if it feels stable.

On a slightly unrelated point, in the Reconnecting section of README you recommend sending PingRequest yourself if you are connecting to a low traffic websocket however I'm not seeing PingRequest anywhere in the codebase, am I missing something?

I ended up turning off reconnection timeout as eventhough my server is sending pings and and receiving responses, the client is still resetting the connection due to not receiving a message (so I assume pings from the server dont count as messages for the sake of of the timeout).

Thanks

Marfusios commented 2 years ago

The documentation is a little confusing here, PingRequest is meant to be a custom pinging feature on the server. Some servers don't support ping (keep-alive) from websockets standard, but provide a separate channel.

So your selected approach is correct if your server support keep-alive, you can set timeout to null. Beware that disabling reconnection will also disable auto reconnection on some network glitch or temporary server outage and you need to reconnect manually.

So it is better to have:

client.IsReconnectionEnabled = true;
client.ReconnectTimeout = null;
zeroed-tech commented 2 years ago

Too easy, thanks for letting me know