2012-06-13 13 views
7

Próbuję utworzyć własnego, prostego robota sieciowego. Chcę pobrać pliki o określonych rozszerzeniach z adresu URL. Mam następujący kod napisany:Dlaczego liczba jednoczesnych pobrań jest ograniczona?

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; 
    } 

Problem polega na tym, że podczas gdy to działa dobrze na 2 równoległych pobrań:

 new ParallelOptions { MaxDegreeOfParallelism = 2, } 

... to nie działa dla większych stopniach równoległości jak:

 new ParallelOptions { MaxDegreeOfParallelism = 5, } 

... i otrzymuję wyjątki limitu czasu połączenia.

Na początku myślałem, że to z powodu WebClient:

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

... ale kiedy zastąpił go funkcji DownloadFile że użył HttpWebRequest nadal mam ten błąd.

Przetestowałem to na wielu stronach internetowych i nic się nie zmieniło. Potwierdziłem również z rozszerzeniem chrome "Download Master", że te serwery pozwalają na wielokrotne pobieranie równoległe. Czy ktoś ma jakiś pomysł, dlaczego mam timeout Wyjątki podczas próby pobrania wielu plików równolegle?

+2

Po prostu ciekawy: dlaczego rzucasz wyjątek po zakończeniu pracy? –

+0

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

+1

Wyjątek, który wyrzucam na końcu, to tymczasowy fragment kodu. Potrzebowałem trochę czasu, aby zobaczyć, kiedy to wszystko zostało zrobione, więc pomyślałem "dlaczego nie?". – NoOne

Odpowiedz

1

O ile mi wiadomo, IIS ograniczy łączną liczbę wejść i wyjść, jednak ta liczba powinna być w zakresie 10^3 nie ~ 5.

Czy możliwe jest testowanie tego samego adresu URL? Wiem, że wiele serwerów WWW ogranicza liczbę jednoczesnych połączeń od klientów. Np .: Czy testujesz, próbując pobrać 10 kopii http://www.google.com?

Jeśli więc warto spróbować testy z listą różnych miejscach, takich jak:

Powiązane problemy