tchelidze
tchelidze

Reputation: 8308

Test connection to server using c#

I want to test if server is alive for given IPEndpoint. I tried the following method but it sometimes returns the wrong result.

public bool IsAlive(IPEndPoint ipEndPoint)
{
  if (ipEndPoint == null) return false;

  var tcpClient = new TcpClient();
  var bConnect = tcpClient.BeginConnect(ipEndPoint.Address, ipEndPoint.Port, null, null);
  var isAlive = bConnect.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(1000));
  return isAlive;
}

What is wrong about this method?

Upvotes: 2

Views: 276

Answers (1)

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

Just because AsyncWaitHandle finished without timing out does not mean it connected successfully. You will need to call tcpClient.EndConnect( and see if it throws a exception, if no exception is thrown all is good, if not the connection is bad. Also, in your original method you where not closing the connection if you did successfully connect.

If you are using .NET 4.5 or newer it is easy to implement, use ConnectAsync instead of the begin/end pair and then you can use await.

public async Task<bool> IsAliveAsync(IPEndPoint ipEndPoint)
{
  if (ipEndPoint == null) return false;

  using(var tcpClient = new TcpClient())
  {
    var connectTask = tcpClient.ConnectAsync(ipEndPoint.Address, ipEndPoint.Port)
    var timeoutTask = Task.Delay(1000);
    var finishedTask = await Task.WhenAny(connectTask, timeoutTask).ConfigureAwait(false);

    bool isAlive;
    if(finishedTask == timeoutTask)
    {
        isAlive = false;
    }
    else
    {
      try
      {
          await connectTask.ConfigureAwait(false);
          isAlive = true;
      }
      catch
      {
        isAlive = false;
      }
    }

    return isAlive;
  }
}

Because I use .ConfigureAwait(false) everywhere I await it should be safe to call .Result on the task returned from this method instead of doing async/await all the way up your call stack.

Upvotes: 1

Related Questions