我正在尝试构建一个c#控制台应用程序,该应用程序将监视约3000个url(只需要知道HEAD请求返回了200个,不一定是内容等)。

我在这里的尝试是建立一个例程来检查Web URL,循环并创建线程,每个线程都执行该例程。发生的情况是,如果我使用 20个线程,则某些url超时。我试图将超时增加到30秒,同样的现象。我在其上运行的网络能够执行50个HTTP HEAD请求(ISP上的10MBIT连接),并且执行例程时CPU和网络的运行都非常低。

发生超时时,我在浏览器上测试了相同的IP,并且可以正常工作,我反复进行了测试,并且在测试过程中从未出现“超时”网址实际上超时的情况。

我想运行20个以上的线程的原因是,我想每5分钟执行一次此测试,其中某些URL会占用整整10秒的时间(如果超时设置得更高,则需要更长的时间),我想确保其能够在2-3分钟内浏览所有网址。

有没有更好的方法来检查URL是否可用,或者我应该在系统/网络中查找问题。

主要

        while (rdr.Read())
        {
            Thread t = new Thread(new ParameterizedThreadStart(check_web));

            t.Start(rdr[0]);


        }




      static void check_web(object weburl)
      {
          bool isok;
          isok = ConnectionAvailable(weburl.ToString());
      }



      public static bool ConnectionAvailable(string strServer)
      {

          try
          {
              strServer = "http://" + strServer;
              HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create(strServer);
              reqFP.Timeout = 10000;
              reqFP.Method = "HEAD";

              HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse();
              if (HttpStatusCode.OK == rspFP.StatusCode)
              {
                  Console.WriteLine(strServer + " - OK");
                  rspFP.Close();
                  return true;
              }
              else
              {
                  Console.WriteLine(strServer + " Server returned error..");
                  rspFP.Close();
                  return false;

              }

          }

          catch (WebException x)
          {
              if (x.ToString().Contains("timed out"))
              {
                  Console.WriteLine(strServer + " - Timed out");
              }
              else
              {
                  Console.WriteLine(x.Message.ToString());
              }

              return false;

          }

      }

最佳答案

请记住,您问过。

实施非常糟糕。


不要去创建这样的线程。拥有比处理器核心更多的线程几乎没有好处。额外的线程几乎只会彼此竞争,特别是因为它们都运行相同的代码。
您需要实现using块。如果抛出异常(很有可能),那么您将在泄漏资源。
返回布尔值的目的是什么?你在某处检查吗?无论如何,您的错误和异常处理都是一团糟。


如果收到非200的响应,则不会显示错误代码。
您正在与Message属性进行比较,以确定是否超时。微软应该在“时间”和“超时”之间留一个空格,以便引起您的注意。
如果不是超时,则仅显示Message属性,而不显示整个异常,并且Message属性已经是一个字符串,不需要您在其上调用ToString()。



下一批变更

这还没有完成,我不认为,但是尝试一下:

public static void Main()
{
    // Don't mind the interpretation. I needed an excuse to define "rdr"
    using (var conn = new SqlConnection())
    {
        conn.Open();
        using (var cmd = new SqlCommand("SELECT Url FROM UrlsToCheck", conn))
        {
            using (var rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                    // Use the thread pool. Please.
                    ThreadPool.QueueUserWorkItem(
                        delegate(object weburl)
                            {
                                // I invented a reason for you to return bool
                                if (!ConnectionAvailable(weburl.ToString()))
                                {
                                    // Console would be getting pretty busy with all
                                    // those threads
                                    Debug.WriteLine(
                                        String.Format(
                                            "{0} was not available",
                                            weburl));
                                }
                            },
                            rdr[0]);
                }
            }
        }
    }
}

public static bool ConnectionAvailable(string strServer)
{
    try
    {
        strServer = "http://" + strServer;
        var reqFp = (HttpWebRequest)WebRequest.Create(strServer);
        reqFp.Timeout = 10000;
        reqFp.Method = "HEAD";

        // BTW, what's an "FP"?
        using (var rspFp = (HttpWebResponse) reqFp.GetResponse()) // IDisposable
        {
            if (HttpStatusCode.OK == rspFp.StatusCode)
            {
                Debug.WriteLine(string.Format("{0} - OK", strServer));
                return true; // Dispose called when using is exited
            }

            // Include the error because it's nice to know these things
            Debug.WriteLine(String.Format(
                 "{0} Server returned error: {1}",
                 strServer, rspFp.StatusCode));
            return false;
        }
    }
    catch (WebException x)
    {
        // Don't tempt fate and don't let programs read human-readable messages
        if (x.Status == WebExceptionStatus.Timeout)
        {
            Debug.WriteLine(string.Format("{0} - Timed out", strServer));
        }
        else
        {
            // The FULL exception, please
            Debug.WriteLine(x.ToString());
        }

        return false;
    }
}


即将完成-未测试深夜代码

public static void Main()
{
    using (var conn = new SqlConnection())
    {
        conn.Open();
        using (var cmd = new SqlCommand("", conn))
        {
            using (var rdr = cmd.ExecuteReader())
            {
                if (rdr == null)
                {
                    return;
                }

                while (rdr.Read())
                {
                    ThreadPool.QueueUserWorkItem(
                        CheckConnectionAvailable, rdr[0]);
                }
            }
        }
    }
}

private static void CheckConnectionAvailable(object weburl)
{
    try
    {
        // If this works, it's a lot simpler
        var strServer = new Uri("http://" + weburl);
        using (var client = new WebClient())
        {
            client.UploadDataCompleted += ClientOnUploadDataCompleted;
            client.UploadDataAsync(
                strServer, "HEAD", new byte[] {}, strServer);
        }
    }
    catch (WebException x)
    {
        Debug.WriteLine(x);
    }
}

private static void ClientOnUploadDataCompleted(
    object sender, UploadDataCompletedEventArgs args)
{
    if (args.Error == null)
    {
        Debug.WriteLine(string.Format("{0} - OK", args.UserState));
    }
    else
    {
        Debug.WriteLine(string.Format("{0} - Error", args.Error));
    }
}

关于c# - HttpWebRequest的局限性?还是执行不好,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1123230/

10-12 00:17
查看更多