2012-06-13 30 views
7

Tôi đang cố gắng tạo trình thu thập dữ liệu web đơn giản của riêng mình. Tôi muốn tải xuống các tệp có tiện ích mở rộng cụ thể từ URL. Tôi đã đoạn mã sau viết:Tại sao có giới hạn về số lượt tải xuống đồng thời?

private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     if (bw.IsBusy) return; 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.RunWorkerAsync(new string[] { URL.Text, SavePath.Text, Filter.Text }); 
    } 
    //-------------------------------------------------------------------------------------------- 
    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      ThreadPool.SetMaxThreads(4, 4); 
      string[] strs = e.Argument as string[]; 
      Regex reg = new Regex("<a(\\s*[^>]*?){0,1}\\s*href\\s*\\=\\s*\\\"([^>]*?)\\\"\\s*[^>]*>(.*?)</a>", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 
      int i = 0; 
      string domainS = strs[0]; 
      string Extensions = strs[2]; 
      string OutDir = strs[1]; 
      var domain = new Uri(domainS); 
      string[] Filters = Extensions.Split(new char[] { ';', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); 
      string outPath = System.IO.Path.Combine(OutDir, string.Format("File_{0}.html", i)); 

      WebClient webClient = new WebClient(); 
      string str = webClient.DownloadString(domainS); 
      str = str.Replace("\r\n", " ").Replace('\n', ' '); 
      MatchCollection mc = reg.Matches(str); 
      int NumOfThreads = mc.Count; 

      Parallel.ForEach(mc.Cast<Match>(), new ParallelOptions { MaxDegreeOfParallelism = 2, }, 
      mat => 
      { 
       string val = mat.Groups[2].Value; 
       var link = new Uri(domain, val); 
       foreach (string ext in Filters) 
        if (val.EndsWith("." + ext)) 
        { 
         Download((object)new object[] { OutDir, link }); 
         break; 
        } 
      }); 
      throw new Exception("Finished !"); 

     } 
     catch (System.Exception ex) 
     { 
      ReportException(ex); 
     } 
     finally 
     { 

     } 
    } 
    //-------------------------------------------------------------------------------------------- 
    private static void Download(object o) 
    { 
     try 
     { 
      object[] objs = o as object[]; 
      Uri link = (Uri)objs[1]; 
      string outPath = System.IO.Path.Combine((string)objs[0], System.IO.Path.GetFileName(link.ToString())); 
      if (!File.Exists(outPath)) 
      { 
       //WebClient webClient = new WebClient(); 
       //webClient.DownloadFile(link, outPath); 

       DownloadFile(link.ToString(), outPath); 
      } 
     } 
     catch (System.Exception ex) 
     { 
      ReportException(ex); 
     } 
    } 
    //-------------------------------------------------------------------------------------------- 
    private static bool DownloadFile(string url, string filePath) 
    { 
     try 
     { 
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 
      request.UserAgent = "Web Crawler"; 
      request.Timeout = 40000; 
      WebResponse response = request.GetResponse(); 
      Stream stream = response.GetResponseStream(); 
      using (FileStream fs = new FileStream(filePath, FileMode.CreateNew)) 
      { 
       const int siz = 1000; 
       byte[] bytes = new byte[siz]; 
       for (; ;) 
       { 
        int count = stream.Read(bytes, 0, siz); 
        fs.Write(bytes, 0, count); 
        if (count == 0) break; 
       } 
       fs.Flush(); 
       fs.Close(); 
      } 
     } 
     catch (System.Exception ex) 
     { 
      ReportException(ex); 
      return false; 
     } 
     finally 
     { 

     } 
     return true; 
    } 

Vấn đề là trong khi nó hoạt động tốt cho 2 tải song song:

 new ParallelOptions { MaxDegreeOfParallelism = 2, } 

... nó không làm việc cho mức độ cao hơn song song như:

 new ParallelOptions { MaxDegreeOfParallelism = 5, } 

... và tôi nhận được ngoại lệ kết nối thời gian chờ.

Lúc đầu, tôi nghĩ đó là vì WebClient:

   //WebClient webClient = new WebClient(); 
       //webClient.DownloadFile(link, outPath); 

... nhưng khi tôi thay thế nó với chức năng DownloadFile rằng sử dụng HttpWebRequest tôi vẫn có những lỗi.

Tôi đã thử nghiệm trên nhiều trang web và không có gì thay đổi. Tôi cũng đã xác nhận với phần mở rộng của chrome, "Tải xuống tổng thể", rằng các máy chủ web này cho phép tải xuống song song nhiều lần. Có ai có bất kỳ ý tưởng nào về lý do tại sao tôi có ngoại lệ thời gian chờ khi cố tải xuống nhiều tệp song song không?

+2

Chỉ cần tò mò: Tại sao bạn ném một ngoại lệ khi công việc được thực hiện? –

+0

http://stackoverflow.com/questions/866350/how-can-i-programmatically-remove-the-2-connection-limit-in-webclient –

+1

Ngoại lệ tôi ném ở cuối là một đoạn mã tạm thời. Tôi cần sth nhanh chóng để xem khi nó đã được thực hiện tất cả, vì vậy tôi nghĩ "tại sao không?". – NoOne

Trả lời

6

Bạn cần chỉ định ServicePointManager.DefaultConnectionLimit. Mặc định kết nối đồng thời cho cùng một máy chủ là 2. Đồng thời xem related SO post về cách sử dụng web.config connectionManagement.

+2

Cảm ơn rất nhiều! Tôi chỉ có nó làm việc bằng cách thiết lập ServicePointManager.DefaultConnectionLimit! Bạn đã cứu tôi rất nhiều thời gian. – NoOne

+0

Làm việc cho tôi! Cảm ơn ! – bernhardrusch

1

Theo như tôi biết IIS sẽ giới hạn tổng số kết nối vào và ra, tuy nhiên con số này phải nằm trong khoảng 10^3 không ~ 5.

Có thể bạn đang thử nghiệm cùng một url không? Tôi biết rất nhiều máy chủ web giới hạn số lượng kết nối đồng thời từ khách hàng. Ví dụ: Bạn có đang thử nghiệm bằng cách cố tải xuống 10 bản sao của http://www.google.com không?

Nếu vậy bạn có thể muốn thử nghiệm với một danh sách các trang web khác nhau như:

Các vấn đề liên quan