1

EDIT: I understand the issue but need a code example to show how to solve it.

I would like for my client to reconnect automatically if it becomes disconnected but it appears TcpClient.Connected is not reliable for it. I've read that you need to send data for the class to change that flag. Is there a better way to handle to problem?

//Method to handle reading data from buffer and deserializing
public static async Task<Message> ReadMessageAsync(this TcpClient client)
{
    if (client.Connected && client.Available > 0)
    {
        int totalBytesRead = 0;
        var data = new byte[client.Available];

        while (totalBytesRead < client.Available)
        {
            totalBytesRead += await client.GetStream().ReadAsync(data, 0, client.Available);
        }

        return BinarySerializer.DeserializeMessage(data) as Message;
    }

    return null;
}

public async Task Start()
{
    ConnectToServer();

    while (_isRunning)
    {
        // Reconnect to server if needed.
        if (!_tcpClient.Connected)
        {
            ConnectToServer();
        }

        // Wait for data
        var data = await _tcpClient.ReadMessageAsync();
            HandleData(data);
    }
}
user3953989
  • 1,844
  • 3
  • 25
  • 56
  • 2
    there's [only one way](https://stackoverflow.com/a/49695769/23354) to know if a socket is working... – Marc Gravell Apr 09 '18 at 15:56
  • Possible duplicate of [How to test for a broken connection of TCPClient after being connected?](https://stackoverflow.com/questions/7650402/how-to-test-for-a-broken-connection-of-tcpclient-after-being-connected) – MrVoid Apr 09 '18 at 15:57
  • @MarcGravell Thanks for the quick response. I believe I understand the last I/O sets the flag just not sure of the best practice for handling the event? Catch the exception and call `Connect` again? Side-note seems like this class expects you to use exceptions for program-flow when that's not good practice? – user3953989 Apr 09 '18 at 16:03
  • 1
    Note that your code will burn your cpu, because if there is no data available in socket (common thing) it basically becomes while(true) loop. – Evk Apr 09 '18 at 16:07
  • Event will not always work. The Event is caused by activity on the Ethernet interface. Disconnecting the cable will cause a disconnect but will not trigger the event. Neither will the server being shutdown cause the event. The only time the event will occur is when the server closes the connection. – jdweng Apr 09 '18 at 16:08
  • @Evk I'm not sure how to solve that. If I use `Thread.Sleep` I'm blocking, just waiting on `ReadAsync` will work but then I can't send a heartbeat to check if the server is still there – user3953989 Apr 09 '18 at 16:59
  • Just use buffer with fixed size and then `await ..ReadAsync(data, 0, buffer.Length);` And you can send a heartbeat, because you can perform write and read operations on network stream at the same time. – Evk Apr 09 '18 at 17:01
  • @Evk Could you provide an example? – user3953989 Apr 09 '18 at 18:04

1 Answers1

1

TCP is a very robust protocol and permits robust programming. For a client, you don´t need to rely on low level signalling from the network interface, the protocol / language offers all you need (unless your client is so time-critical that it need immediate notification of a network failure):

Connecting:

  • if connection fails, try again (after a suitable timeout) or give up

Receiving:

  • set an appropriate receive timeout and act accordingly when the timeout exception is thrown (either close the socket and start over again or give up, or notify the user or ...). Will "signal" that the server died, or the internet died or ...
  • check for bytes received == 0 (indicates a graceful disconnection from the other side, FIN) and act accordingly
  • if the other side sends a RST, you´ll get an exception, handle that accordingly.
C. Gonzalez
  • 689
  • 7
  • 8