2012-06-13 9 views
7

Estoy tratando de hacer mi propio rastreador web simple. Quiero descargar archivos con extensiones específicas de una URL. He escrito el siguiente código:¿Por qué hay un límite en el número simultáneo de descargas?

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

El problema es que, aunque funciona bien para 2 descargas paralelas:

 new ParallelOptions { MaxDegreeOfParallelism = 2, } 

... no funciona para un mayor grado de paralelismo como:

 new ParallelOptions { MaxDegreeOfParallelism = 5, } 

... y obtengo excepciones de tiempo de espera de conexión.

Al principio pensé que era debido a WebClient:

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

... pero cuando lo reemplazó con la función DownloadFile que utiliza el HttpWebRequest yo todavía tengo el error.

Lo he probado en muchas páginas web y nada ha cambiado. También he confirmado con la extensión de Chrome, "Download Master", que estos servidores web permiten múltiples descargas paralelas. ¿Alguien tiene alguna idea de por qué tengo excepciones de tiempo de espera al intentar descargar muchos archivos en paralelo?

+2

Simplemente curioso: ¿Por qué lanzas una excepción cuando el trabajo está hecho? –

+0

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

+1

La excepción que arrojo al final es una pieza temporal de código. Necesitaba algo rápido para ver cuando todo estaba hecho, así que pensé "¿por qué no?". – NoOne

Respuesta

1

Hasta donde yo sé IIS limitará el número total de conexiones dentro y fuera, sin embargo, este número debe estar en el rango de 10^3 no ~ 5.

¿Es posible que esté realizando pruebas en la misma URL? Sé que muchos servidores web limitan la cantidad de conexiones simultáneas de los clientes. Ejemplo: ¿Está probando tratando de descargar 10 copias de http://www.google.com?

Si es así es posible que desee probar la prueba con una lista de sitios diferentes, tales como:

Cuestiones relacionadas