Matt Burland
Matt Burland

Reputation: 45135

Web socket stops responding after awhile

I have a windows service that uses a websocket (from http://sta.github.io/websocket-sharp/) to conenct to Slack and monitor messages.

My connection code looks something like this:

ws = new WebSocket(connection.Url);

ws.OnMessage += async (sender, e) =>
{
    var msg = JsonConvert.DeserializeObject<MessageFromSlack>(e.Data);
    if (msg.Type == "message" && msg.Text != null && msg.User != UserId)
    {
        if (userMatcher.IsMatch(msg.Text))
        {
            await ProcessDirectMessage(msg);
        }
        await ProcessMessage(msg);
    }
    if (msg.Type == "channel_joined")
    {
        await ChannelJoined(msg.ChannelModel.Id);
    }
};

ws.OnClose += (sender, e) =>
{
    var reason = e.Reason;
    var code = e.Code;
    System.Diagnostics.Debug.WriteLine($"{code}:{reason}");
};

ws.Connect();

Basically it waits for a message and then if it's directed @ my bot, it'll call ProcessDirectMessage and if not it'll call ProcessMessage. The details of those functions are, I think, unimportant (they do some matching looking for key phrases and respond by sending a message back).

This all works fine. For a while. But after some period of time (usually more than a day), it just stops responding altogether. My OnMessage handler never gets hit. I thought that maybe what is happening is the websocket is getting closed on the server side, so I added the OnClose handler, but that never seems to get hit either.

Does anybody have an idea what might be happening here? Is there a way to keep the connection alive, or else reconnect it when it dies?

Upvotes: 2

Views: 3335

Answers (1)

Evk
Evk

Reputation: 101453

By the nature of TCP connection - the only reliable way to detect its gone is to write something to it. If you are just reading (waiting for data to arrive) - you can do that for a very long time while the other side is long time dead. That happens if that other side did not close connection gracefully (which involves an exchange of some TCP packets).

Web socket protocol defines special Ping frame, and corresponding Pong frame, which you should use to avoid situation described in the question. From time to time you should send Ping frame and wait (for a certain timeout) for server to respond with Pong frame. If it did not respond in given timeout - assume connection is dead and reconnect.

As far as I know - library you use does not automatically send ping requests on your behalf. However, it allows you to do that via Ping method.

You need to configure timeout with

ws.WaitTime = TimeSpan.FromSeconds(5);

And then, from time to time (for example - when you did not receive any new messages in last X seconds), do:

bool isAlive = ws.Ping();

There is also boolean property which does the same:

bool isAlive = ws.IsAlive;

This is a blocking call (both of the above). It will return true if server replied with Pong during ws.WaitTime interval, and false otherwise. Then you can act accordingly.

Upvotes: 4

Related Questions