使用c#测试与服务器的连接

时间:2016-01-06 14:50:52

标签: c# networking tcpclient

我想测试服务器是否处于给定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;
}

这种方法有什么问题?

1 个答案:

答案 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你的通话栈的方式。