Reputation: 8308
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
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