我想测试服务器是否处于给定IPEndpoint
的活动状态。我尝试了以下方法,但有时会返回错误的结果。
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;
}
这种方法有什么问题?
答案 0 :(得分:1)
仅仅因为AsyncWaitHandle
完成而没有超时并不意味着它已成功连接 。您将需要调用tcpClient.EndConnect(
并查看它是否抛出异常,如果没有抛出异常,则一切都很好,如果不是连接错误。此外,在原始方法中,如果成功连接,则不关闭连接。
如果您使用的是.NET 4.5或更新版本,则很容易实现,使用ConnectAsync
代替开始/结束对,然后您可以使用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;
}
}
因为我在.ConfigureAwait(false)
处使用await
,所以应该可以安全地从此方法返回的任务上调用.Result
而不是async / await all你的通话栈的方式。