c# Detect when ClientWebSocket is disconnected (closed)

J-Go picture J-Go · Jan 23, 2018 · Viewed 8.4k times · Source

After a long search i come to you to help me.

I have a WPF application, use ClientWebSocket class (using System.Net.WebSockets) to connect to WebSocket server(NodeJS). My application is running backgroung windows application, it connects at first time, and then, in timer of 1 minute try to re-connect (if not already connected). But when i disable the connexion (Network connection), my application doesn't detect that, so evry 1 minute tells me that it's connected. I know there is something wrong in my code, and i don't know how implement an event handler to be informed if the connetion is losed (websocket closed).

I note that when i connect to the server, i must create a session, then i receive a session_id, and now i'm connected to websocket server.

Class1 is a libreary class that i use WebSockets class

class1
{
    ClientWebSocket web_socket;
    bool connected = false;
    public async Task<bool> connect_socket()
    { 
        Object result_object;
        string session_id;
        try
        {
            if (connected == false)
            {
                web_socket = new ClientWebSocket();
                web_socket.Options.SetRequestHeader("headername", "headerValue");
                await web_socket.ConnectAsync(new Uri(" ... uri....."), CancellationToken.None);

                create_session();

                ArraySegment<byte> byte_received = new ArraySegment<byte>(new byte[1024]);
                WebSocketReceiveResult json_notify_result = await web_socket.ReceiveAsync(byte_received, CancellationToken.None);
                string string_notify = Encoding.UTF8.GetString(byte_received.Array);
                json_notify = JsonConvert.DeserializeObject<Dictionary<string, object>>(string_notify);

                if (json_notify.TryGetValue("result", out result_object))
                {
                    var result = JsonConvert.DeserializeObject<Dictionary<string, string>>((result_object).ToString());
                    if (result.TryGetValue("session_id", out session_id) && (string)session_id != null)
                        Debug.WriteLine("session_id = " + session_id);
                }
                 connected = true;
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
         return connected;
    }
}

In my Class2 i use Class1

Class2
{
    Class2()
    {
        InitializeComponent();
        timer = new System.Threading.Timer(timer_callback, null, 0, 60000);
    }
    public void timer_callback()
    {
        if (Class1.connected == false)
        {
            Class1.connect_socket().Wait();
        }      
    }
}

For any suggestion, i'll be very grateful. I am really stuck in this point

Answer

Gor Rustamyan picture Gor Rustamyan · Jan 23, 2018

You are using System.Threading.Timer which is running timer_callback on thread pool thread. So any exceptions thrown timer_callback in timer callback will be swallowed. So exception thrown by web_socket.ConnectAsync when you drop connection, will be swallowed as well.

Also try checking socket close message.

 var res = await webSocket.ReceiveAsync(segment, cancellation);
 if (res.MessageType == WebSocketMessageType.Close)
     return false;