title: cURL with multi interface for many connections with proxy
body: <p>I need to check many proxies from list against one website. I decided to use libcurl to do this.<br>
  I used <a href="http://curl.haxx.se/libcurl/c/multi-app.html" rel="nofollow">this</a> example and modified it according to my needs.<br>
  Here  is my code:</p>
  
  <pre><code>#include &lt;cstdio&gt;
  #include &lt;cstring&gt;
  #include &lt;fstream&gt;
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  
  #include &lt;curl/curl.h&gt;
  
  /* somewhat unix-specific */ 
  #include &lt;sys/time.h&gt;
  #include &lt;unistd.h&gt;
  
  using namespace std;
  
  CURL * handles [100];
  
  CURL * createProxyHandle (string proxyData){
      CURL * handle = curl_easy_init ();
  
      curl_slist * chunk = NULL;
      chunk = curl_slist_append(chunk, "Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1");
      chunk = curl_slist_append(chunk, "Accept-Language: ru-RU,ru;q=0.9,en;q=0.8");
      chunk = curl_slist_append(chunk, "Accept-Encoding: gzip, deflate, sdch");
  
      curl_easy_setopt (handle, CURLOPT_URL, "&lt;site&gt;");
      curl_easy_setopt (handle, CURLOPT_CONNECTTIMEOUT, 40);
      curl_easy_setopt (handle, CURLOPT_TIMEOUT, 50);
      curl_easy_setopt (handle, CURLOPT_FRESH_CONNECT, true);
      curl_easy_setopt (handle, CURLOPT_VERBOSE, true);
      curl_easy_setopt (handle, CURLOPT_FOLLOWLOCATION, true);
  
      curl_easy_setopt (handle, CURLOPT_ENCODING , "gzip");
      curl_easy_setopt (handle, CURLOPT_PROXY, proxyData.c_str());
      curl_easy_setopt (handle, CURLOPT_HTTPHEADER, chunk);
      curl_easy_setopt (handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36");
  
      return handle;
  }
  
  int main(){
      ifstream fin ("data.txt", ifstream::in);
      string proxy;
  
      CURLM *multi_handle;
      CURLMsg *msg;
  
      int msgs_left;
      int still_running;
  
  
  
      multi_handle = curl_multi_init();
  
      while (fin &gt;&gt; proxy){
          cout &lt;&lt; "Proxy: " &lt;&lt; proxy &lt;&lt; endl;
          CURL * handle = createProxyHandle (proxy);
          curl_multi_add_handle(multi_handle, handle);
      }
  
      curl_multi_perform(multi_handle, &amp;still_running);
  
  do {
      struct timeval timeout;
      int rc; /* select() return code */ 
      CURLMcode mc; /* curl_multi_fdset() return code */ 
  
      fd_set fdread;
      fd_set fdwrite;
      fd_set fdexcep;
      int maxfd = -1;
  
      long curl_timeo = -1;
  
      FD_ZERO(&amp;fdread);
      FD_ZERO(&amp;fdwrite);
      FD_ZERO(&amp;fdexcep);
  
      /* set a suitable timeout to play around with */ 
      timeout.tv_sec = 1;
      timeout.tv_usec = 0;
  
      curl_multi_timeout(multi_handle, &amp;curl_timeo);
      if(curl_timeo &gt;= 0) {
        timeout.tv_sec = curl_timeo / 1000;
        if(timeout.tv_sec &gt; 1)
          timeout.tv_sec = 1;
        else
          timeout.tv_usec = (curl_timeo % 1000) * 1000;
      }
  
      /* get file descriptors from the transfers */ 
      mc = curl_multi_fdset(multi_handle, &amp;fdread, &amp;fdwrite, &amp;fdexcep, &amp;maxfd);
  
      if(mc != CURLM_OK)
      {
        fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
        break;
      }
  
      /* On success the value of maxfd is guaranteed to be &gt;= -1. We call
         select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
         no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
         to sleep 100ms, which is the minimum suggested value in the
         curl_multi_fdset() doc. */ 
  
      if(maxfd == -1) {
  #ifdef _WIN32
        Sleep(100);
        rc = 0;
  #else
        /* Portable sleep for platforms other than Windows. */ 
        struct timeval wait = { 0, 100 * 1000 }; /* 100ms */ 
        rc = select(0, NULL, NULL, NULL, &amp;wait);
  #endif
      }
      else {
        /* Note that on some platforms 'timeout' may be modified by select().
           If you need access to the original value save a copy beforehand. */ 
        rc = select(maxfd+1, &amp;fdread, &amp;fdwrite, &amp;fdexcep, &amp;timeout);
      }
  
      switch(rc) {
      case -1:
        /* select error */ 
        break;
      case 0:
      default:
        /* timeout or readable/writable sockets */ 
        curl_multi_perform(multi_handle, &amp;still_running);
        break;
      }
    } while(still_running);
  
     while ((msg = curl_multi_info_read(multi_handle, &amp;msgs_left))) {
          if (msg-&gt;msg == CURLMSG_DONE) {
            printf("Finished with %d\n", msg-&gt;data.result);
          }
        }
      cout &lt;&lt; "Completed" &lt;&lt; endl;
      curl_multi_cleanup(multi_handle);
  
      return 0;
  }
  </code></pre>
  
  <p>Proxies are not reliable, but what I see in output:</p>
  
  <pre><code>Proxy: 69.12.64.105:8089
  Proxy: 69.12.64.105:7808
  Proxy: 210.245.20.170:80
  Proxy: 190.74.165.109:8080
  Proxy: 39.184.2.111:8123
  Proxy: 190.201.166.37:8080
  Proxy: 190.36.85.199:8080
  Proxy: 92.255.231.54:8080
  Proxy: 124.126.126.101:80
  Proxy: 43.250.255.65:8080
  Proxy: 69.12.64.106:7808
  Proxy: 201.217.213.166:8080
  Proxy: 178.169.90.188:8888
  Proxy: 124.248.205.25:8080
  Proxy: 39.190.82.133:8123
  Proxy: 190.77.230.36:8080
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 69.12.64.105...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 69.12.64.105...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 210.245.20.170...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 190.74.165.109...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 39.184.2.111...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 190.201.166.37...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 190.36.85.199...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 92.255.231.54...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 124.126.126.101...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 43.250.255.65...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 69.12.64.106...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 201.217.213.166...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 178.169.90.188...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 124.248.205.25...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 39.190.82.133...
  * Rebuilt URL to: &lt;site&gt;
  * Hostname was NOT found in DNS cache
  *   Trying 190.77.230.36...
  * Connected to 69.12.64.105 (69.12.64.105) port 8089 (#0)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  &lt; HTTP/1.1 503 Service Unavailable
  &lt; Server: squid/3.2.13
  &lt; Mime-Version: 1.0
  &lt; Date: Mon, 20 Apr 2015 23:00:24 GMT
  &lt; Content-Type: text/html
  &lt; Content-Length: 3694
  &lt; X-Squid-Error: ERR_DNS_FAIL 0
  &lt; 
  * Received HTTP code 503 from proxy after CONNECT
  * Connected to 69.12.64.105 (69.12.64.105) port 7808 (#1)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  &lt; HTTP/1.1 503 Service Unavailable
  &lt; Server: squid/3.2.13
  &lt; Mime-Version: 1.0
  &lt; Date: Mon, 20 Apr 2015 23:00:25 GMT
  &lt; Content-Type: text/html
  &lt; Content-Length: 3694
  &lt; X-Squid-Error: ERR_DNS_FAIL 0
  &lt; 
  * Received HTTP code 503 from proxy after CONNECT
  * Connected to 43.250.255.65 (43.250.255.65) port 8080 (#9)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  &lt; HTTP/1.1 200 OK
  &lt; 
  * Proxy replied OK to CONNECT request
  * found 173 certificates in /etc/ssl/certs/ca-certificates.crt
  * Connected to 69.12.64.106 (69.12.64.106) port 7808 (#10)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  &lt; HTTP/1.1 200 Connection established
  &lt; 
  * Proxy replied OK to CONNECT request
  * found 173 certificates in /etc/ssl/certs/ca-certificates.crt
  * Connected to 190.77.230.36 (190.77.230.36) port 8080 (#15)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  &lt; HTTP/1.0 200 Connection established
  &lt; Proxy-agent: tinyproxy/1.8.2
  &lt; 
  * Proxy replied OK to CONNECT request
  * found 173 certificates in /etc/ssl/certs/ca-certificates.crt
  * Connected to 39.184.2.111 (39.184.2.111) port 8123 (#4)
  * Establish HTTP proxy tunnel to &lt;site&gt;:443
  &gt; CONNECT &lt;site&gt;:443 HTTP/1.1
  Host: &lt;site&gt;:443
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
  Proxy-Connection: Keep-Alive
  Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
  Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
  Accept-Encoding: gzip, deflate, sdch
  
  * Proxy CONNECT aborted due to timeout
  * Connection time-out
  * Closing connection 5
  * Connection time-out
  * Closing connection 6
  * Connection time-out
  * Closing connection 7
  * Connection time-out
  * Closing connection 8
  * SSL connection timeout
  * Closing connection 9
  * SSL connection timeout
  * Closing connection 10
  * Connection time-out
  * Closing connection 11
  * Connection time-out
  * Closing connection 12
  * Connection time-out
  * Closing connection 13
  * Connection time-out
  * Closing connection 14
  * SSL connection timeout
  * Closing connection 15
  * Connection timed out after 50056 milliseconds
  * Connection timed out after 50055 milliseconds
  Finished with 56
  Finished with 56
  Finished with 56
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Finished with 28
  Completed
  </code></pre>
  
  <p>In some cases (really a lot of proxies are bad, but not all in this list) curl receives answers from proxies, sends headers, but nothing more. I tested this proxies separated and they are OK.<br>
  I can not figure what is happening with curl multi.</p>