websocket-client icon indicating copy to clipboard operation
websocket-client copied to clipboard

Connection and disconnection and issues

Open mradovcic opened this issue 4 years ago • 6 comments

Hi, I have an issue with constant disconnection and reconnection from wss server, every time it reconnects it disconnects immediately. This is the code (.netCore hosted service):

public async Task StartAsync(CancellationToken cancellationToken)
{
    try
    {
        var url = new Uri(wssServer);
        var factory = new Func<ClientWebSocket>(() => new ClientWebSocket
        {
            Options =
            {
                KeepAliveInterval = TimeSpan.FromSeconds(5),
                Credentials = new NetworkCredential(username, password)
            }
        });
        _wssClient = new WebsocketClient(url, factory);
        _wssClient.ReconnectTimeout = null;

        _wssClient.DisconnectionHappened.Subscribe(async type =>
        {
            await _logger.Write($"Disconnected at {DateTime.UtcNow}. Type: {JsonConvert.SerializeObject(type)}");
            await Task.Delay(60 * 1000);
            await ReconnectToWSS();
        });

        _wssClient.MessageReceived.Subscribe(async msg => await OnMessage(msg.Text));

        new Task(async () => await ConnectToWSS()).Start();
    }
    catch (Exception ex)
    {
        await _logger.WriteException(ex);
    }
}

public async Task StopAsync(CancellationToken cancellationToken)
{
    try
    {
        await _wssClient.StopOrFail(WebSocketCloseStatus.NormalClosure, "Stream closing.");
    }
    catch(Exception e)
    {
        await _logger.WriteException(e);
    }

    await _logger.Write($"Stopped at {DateTime.UtcNow}.");
    _wssClient.Dispose();
}

private async Task ReconnectToWSS()
{
    try
    {
        await _wssClient.ReconnectOrFail();
        _logger.Write($"Reconnected at {DateTime.UtcNow}");
    }
    catch(Exception e)
    {
        await _logger.WriteException(e);
        await Task.Delay(60 * 1000);
        await ReconnectToWSS();
    }
}

private async Task ConnectToWSS()
{
    try 
    {
        await _wssClient.StartOrFail();
        await _logger.Write($"Connected at {DateTime.UtcNow}.");
    }
    catch(Exception e)
    {
        await _logger.WriteException(e);
        await Task.Delay(60 * 1000);
        await ConnectToWSS();
    }
}

and it logs this every minute

Reconnected at 01/27/2020 08:51:28

Disconnected at 01/27/2020 08:51:28. Type: {"Type":4,"CloseStatus":null,"CloseStatusDescription":null,"SubProtocol":null,"Exception":null,"CancelReconnection":false,"CancelClosing":false}

Most unusual thing is the disconnection type 4

//
// Summary:
//     Type used when disconnection was requested by user
ByUser = 4,

Thanks in advance for any help!

mradovcic avatar Jan 27 '20 08:01 mradovcic

Hello @mradovcic,

unfortunately can't help you. At first sight, there is no serious issue with your code. ByUser means that your code definitely called method Reconnect or ReconnectOrFail at some point, so put there breakpoints and check callstack who called it and why.

Also, you are reinventing the wheel, reconnection is already implemented inside WebsocketClient. You are really messing with threads, just call:

public async Task StartAsync(CancellationToken cancellationToken) {
    // ....
    _ = _wssClient.Start();
    return Task.Completed;
}

It will notify you via DisconnectionHappened or ReconnectionHappened streams if something fails.

Marfusios avatar Jan 27 '20 21:01 Marfusios

Hello @Marfusios First of all, thank You for responding.

Also, you are reinventing the wheel, reconnection is already implemented inside WebsocketClient

I've used to use the implemented reconnection handling but I've switched to this while trying to solve this issue (didn't help obviously)

You are really messing with threads, just call:

public async Task StartAsync(CancellationToken cancellationToken) {
    // ....
    _ = _wssClient.Start();
    return Task.Completed;
}

I've used to have an issue, when wss server wasn't available or url wasn't correct, API wouldn't start properly and when I try to stop the process it would get stuck at _wssClient.Dispose();

I will definitely check my call stack once again and update You if I make any progress.

mradovcic avatar Jan 27 '20 21:01 mradovcic

Ok, let me know. I see, then use:

public async Task StartAsync(CancellationToken cancellationToken) {
    // ....
    await _wssClient.StartOrFail();
}

Don't forget to enable verbose logging, it helps a lot. https://github.com/Marfusios/websocket-client/blob/master/test_integration/Websocket.Client.Sample/Program.cs#L118

Marfusios avatar Jan 28 '20 10:01 Marfusios

Hi @mradovcic. I seem to have the exact same problem. Do you remember how you solved this?

Madsens avatar Sep 15 '21 09:09 Madsens

@Madsens Honestly, I switched to PureWebSockets https://github.com/coinigy/PureWebSockets and completely forgot about this. But if You make any progress let me know.

mradovcic avatar Sep 15 '21 09:09 mradovcic

@mradovcic thank you for your quick reply! I tried to fix this all night, and I think i helped asking you, because i finally found the solution. I thought about what @Marfusios said about reinventing the wheel, so i disabled all of my own code reconnecting after a disconnection, and reenabled the automatic reconnecting, which it default does every 60 seconds, and it seems to work perfectly.

I'm connected to Amazon / AWS, and it has a max connection time of 2 hours. After that, my code reconnects after 60 seconds just as intended. (I have a Cron on AWS asking my client for info every 60 seconds, so the connection is kept alive throughout the 2 hours)

Madsens avatar Sep 15 '21 12:09 Madsens