How to check if client disconnected abruptly

Asked

Viewed 108 times

1

I have this online chat code using socket and TCPListener, but when the client simply disconnects abruptly or loses connection, it is not removed from the ArrayList so-called clients.

public void ServiceClient()
    {
        Socket client = clientsocket;
        bool keepalive = true;

        while (keepalive)
        {
            Byte[] buffer = new Byte[1024];
            client.Receive(buffer);
            string clientcommand = System.Text.Encoding.UTF8.GetString(buffer);

            string[] tokens = clientcommand.Split(new Char[] { '|' });
            Console.WriteLine(clientcommand);

            if (tokens[0] == "CONN")
            {
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, "JOIN|" + tokens[1]);
                }
                EndPoint ep = client.RemoteEndPoint;
                //string add = ep.ToString();
                Client c = new Client(tokens[1], ep, clientservice, client);
                clients.Add(c);
                string message = "LIST|" + GetChatterList() + "\r\n";
                SendToClient(c, message);
                this.Invoke(new Action(() => lbClients.Items.Add(c.Name)));

                //txtLogs.AppendText("-> SISTEMA: ", Color.Red);
                //txtLogs.AppendText(DateTime.Now.ToString("HH:mm:ss") + "h - " + "Entrou no chat: " + c.Name, Color.White);
                //txtLogs.AppendText("\r\n");
            }
            else if (tokens[0] == "CHAT")
            {
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    this.Invoke(new Action(() => SendToClient(cl, clientcommand)));
                    str = clientcommand;
                    var charsToRemove = new string[] { "CHAT|" };
                    foreach (var c in charsToRemove)
                    {
                        str = str.Replace(c, string.Empty);
                    }
                }
                //txtLogs.AppendText("-> CHAT: ", Color.DodgerBlue);
                //txtLogs.AppendText(str, Color.White);
            }
            if (tokens[0] == "PRIV")
            {
                string destclient = tokens[3];
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];

                    if (cl.Name.CompareTo(tokens[3]) == 0)
                    {
                        SendToClient(cl, clientcommand);
                        var str = clientcommand;
                        var charsToRemove = new string[] { "PRIV|", "|", tokens[3] };
                        foreach (var c in charsToRemove)
                        {
                            str = str.Replace(c, string.Empty);
                        }
                        txtLogs.AppendText("-> PRIVADO: ", Color.Gold);
                        txtLogs.AppendText("Para: ", Color.LimeGreen);
                        txtLogs.AppendText(tokens[3], Color.White);
                        txtLogs.AppendText(" De: ", Color.LimeGreen);
                        txtLogs.AppendText(str, Color.White);
                        txtLogs.AppendText("\r\n");
                    }
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        SendToClient(cl, clientcommand);
                        var str = clientcommand;
                        var charsToRemove = new string[] { "PRIV|", "|", tokens[1] };
                        foreach (var c in charsToRemove)
                        {
                            str = str.Replace(c, string.Empty);
                        }
                        txtLogs.AppendText("-> PRIVADO: ", Color.Gold);
                        txtLogs.AppendText("Para: ", Color.LimeGreen);
                        txtLogs.AppendText(tokens[1], Color.White);
                        txtLogs.AppendText(" De: ", Color.LimeGreen);
                        txtLogs.AppendText(str, Color.White);
                        txtLogs.AppendText("\r\n");
                    }
                }
            }
            else if (tokens[0] == "GONE")
            {
                int remove = 0;
                bool found = false;
                int c = clients.Count;
                for (int n = 0; n < c; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        remove = n;
                        found = true;
                        this.Invoke(new Action(() => lbClients.Items.Remove(cl.Name)));

                        txtLogs.AppendText("-> SISTEMA: ", Color.Red);
                        txtLogs.AppendText(DateTime.Now.ToString("HH:mm:ss") + "h - " + "Saiu no chat: " + cl.Name, Color.White);
                        txtLogs.AppendText("\r\n");
                    }
                }
                if (found)
                    clients.RemoveAt(remove);
                client.Close();
                keepalive = false;
            }
            /*else
            {
                int remove = 0;
                bool found = false;
                int c = clients.Count;
                for (int n = 0; n < c; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        remove = n;
                        found = true;
                        lbClients.Items.Remove(cl);
                        //lbClients.Items.Remove(cl.Name + " : " + cl.Host.ToString());
                    }
                }
                if (found)
                    this.Invoke(new Action(() => clients.RemoveAt(remove)));
                client.Close();
                keepalive = false;
            }*/
        }
    }

With this, how to know if the customer is no longer operating and how to remove it from the ArrayList and of ListBox?

1 answer

1

One way to do this control is for the client to keep sending messages to the server for a predetermined time.

For example, even if the client has no message to send to the server, every 5 seconds it should send a message "I am here".

The server must control the reception times for each client. If the server does not receive a message from a client for 7 seconds (every 5 seconds the client must send a message, and another 2 seconds of tolerance) then the server removes the client from its client list.

I don’t work with C# but second this MSDN page when you set up Receivetimeout in socket you need to treat exceptions.

In this link of MSDN I put there is an example of handling exceptions, I am putting here:

// Displays sending with a connected socket
// using the overload that takes a buffer and socket flags.
public static int SendReceiveTest2(Socket server)
{
    byte[] msg = Encoding.UTF8.GetBytes("This is a test");
    byte[] bytes = new byte[256];
    try  // <------------------- VEJA ISTO
    {
        // Blocks until send returns.
        int byteCount = server.Send(msg, SocketFlags.None);
        Console.WriteLine("Sent {0} bytes.", byteCount);

        // Get reply from the server.
        byteCount = server.Receive(bytes, SocketFlags.None);
        if (byteCount > 0)
            Console.WriteLine(Encoding.UTF8.GetString(bytes));
    }
    catch (SocketException e) // <------------- VEJA ISTO
    {
        Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);
        return (e.ErrorCode);
    }
    return 0;
}
  • I do it with a ReceiveTimeout in the Socket?

  • At the moment, adding the ReceiveTimeout when there is abrupt disconnection, the server returns this: "It has been forced to cancel an existing connection by the remote host"

  • think that this message you showed does not refer to the expired timeout, but rather to the socket closure by the client...to test the timeout control on the server you should leave the client running, but not sending anything to the server

Browser other questions tagged

You are not signed in. Login or sign up in order to post.