2012-06-13 31 views
7

मैं अपना खुद का सरल वेब क्रॉलर बनाने की कोशिश कर रहा हूं। मैं एक यूआरएल से विशिष्ट एक्सटेंशन के साथ फाइलें डाउनलोड करना चाहता हूं। मैं निम्नलिखित कोड लिखा है:समवर्ती डाउनलोड की संख्या में कोई सीमा क्यों है?

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

समस्या यह है कि जब यह 2 समानांतर डाउनलोड के लिए ठीक काम करता है:

 new ParallelOptions { MaxDegreeOfParallelism = 2, } 

... ऐसा लगता है जैसे समानांतरवाद का अधिक से अधिक डिग्री के लिए काम नहीं करता:

 new ParallelOptions { MaxDegreeOfParallelism = 5, } 

... और मुझे कनेक्शन टाइमआउट अपवाद मिलते हैं।

पहले तो मैंने सोचा कि यह WebClient की वजह से था:

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

... लेकिन जब मैं समारोह DownloadFile कि HttpWebRequest इस्तेमाल किया से बदल दिया मैं अभी भी त्रुटि मिली।

मैंने इसे कई वेब पृष्ठों पर परीक्षण किया है और कुछ भी नहीं बदला है। मैंने क्रोम के एक्सटेंशन, "मास्टर डाउनलोड" के साथ भी पुष्टि की है, कि ये वेब सर्वर एकाधिक समानांतर डाउनलोड की अनुमति देते हैं। क्या किसी को भी कोई विचार है कि मुझे समयावधि में कई फ़ाइलों को डाउनलोड करने का प्रयास करते समय टाइमआउट अपवाद क्यों मिलता है?

+2

बस उत्सुक: काम पूरा होने पर आप अपवाद क्यों फेंकते हैं? –

+0

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

+1

अंत में जो अपवाद मैं फेंकता हूं वह कोड का एक अस्थायी टुकड़ा है। मुझे यह देखने के लिए जल्दी से जरूरत थी कि यह सब कब किया गया था, इसलिए मैंने सोचा "क्यों नहीं?"। – NoOne

उत्तर

6

आपको ServicePointManager.DefaultConnectionLimit असाइन करने की आवश्यकता है। डिफ़ॉल्ट समान होस्ट के लिए समवर्ती कनेक्शन 2. वेब.config connectionManagement का उपयोग करने पर related SO post भी देखें।

+2

बहुत बहुत धन्यवाद! मुझे बस ServicePointManager.DefaultConnectionLimit सेट करके काम कर रहा है! आपने मुझे बहुत समय बचा लिया है। – NoOne

+0

मेरे लिए भी काम किया! धन्यवाद ! – bernhardrusch

1

जहां तक ​​मुझे पता है कि आईआईएस कनेक्शन की कुल संख्या को सीमित और सीमित कर देगा, हालांकि यह संख्या 10^3 नहीं ~ 5 की सीमा में होनी चाहिए।

क्या यह संभव है कि आप उसी यूआरएल से परीक्षण कर रहे हों? मुझे पता है कि बहुत सारे वेब सर्वर ग्राहकों से एक साथ कनेक्शन की संख्या सीमित करते हैं। पूर्व: क्या आप http://www.google.com की 10 प्रतियां डाउनलोड करने का प्रयास कर परीक्षण कर रहे हैं?

तो आप इस तरह के रूप में विभिन्न साइटों की एक सूची के साथ परीक्षण का प्रयास करना चाहें तो:

संबंधित मुद्दे