Home | History | Annotate | Download | only in examples
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 /* <DESC>
     23  * Source code using the multi interface to download many
     24  * files, with a capped maximum amount of simultaneous transfers.
     25  * </DESC>
     26  * Written by Michael Wallner
     27  */
     28 
     29 #include <errno.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #ifndef WIN32
     33 #  include <unistd.h>
     34 #endif
     35 #include <curl/multi.h>
     36 
     37 static const char *urls[] = {
     38   "http://www.microsoft.com",
     39   "http://www.opensource.org",
     40   "http://www.google.com",
     41   "http://www.yahoo.com",
     42   "http://www.ibm.com",
     43   "http://www.mysql.com",
     44   "http://www.oracle.com",
     45   "http://www.ripe.net",
     46   "http://www.iana.org",
     47   "http://www.amazon.com",
     48   "http://www.netcraft.com",
     49   "http://www.heise.de",
     50   "http://www.chip.de",
     51   "http://www.ca.com",
     52   "http://www.cnet.com",
     53   "http://www.news.com",
     54   "http://www.cnn.com",
     55   "http://www.wikipedia.org",
     56   "http://www.dell.com",
     57   "http://www.hp.com",
     58   "http://www.cert.org",
     59   "http://www.mit.edu",
     60   "http://www.nist.gov",
     61   "http://www.ebay.com",
     62   "http://www.playstation.com",
     63   "http://www.uefa.com",
     64   "http://www.ieee.org",
     65   "http://www.apple.com",
     66   "http://www.symantec.com",
     67   "http://www.zdnet.com",
     68   "http://www.fujitsu.com",
     69   "http://www.supermicro.com",
     70   "http://www.hotmail.com",
     71   "http://www.ecma.com",
     72   "http://www.bbc.co.uk",
     73   "http://news.google.com",
     74   "http://www.foxnews.com",
     75   "http://www.msn.com",
     76   "http://www.wired.com",
     77   "http://www.sky.com",
     78   "http://www.usatoday.com",
     79   "http://www.cbs.com",
     80   "http://www.nbc.com",
     81   "http://slashdot.org",
     82   "http://www.bloglines.com",
     83   "http://www.techweb.com",
     84   "http://www.newslink.org",
     85   "http://www.un.org",
     86 };
     87 
     88 #define MAX 10 /* number of simultaneous transfers */
     89 #define CNT sizeof(urls)/sizeof(char *) /* total number of transfers to do */
     90 
     91 static size_t cb(char *d, size_t n, size_t l, void *p)
     92 {
     93   /* take care of the data here, ignored in this example */
     94   (void)d;
     95   (void)p;
     96   return n*l;
     97 }
     98 
     99 static void init(CURLM *cm, int i)
    100 {
    101   CURL *eh = curl_easy_init();
    102 
    103   curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, cb);
    104   curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
    105   curl_easy_setopt(eh, CURLOPT_URL, urls[i]);
    106   curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]);
    107   curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
    108 
    109   curl_multi_add_handle(cm, eh);
    110 }
    111 
    112 int main(void)
    113 {
    114   CURLM *cm;
    115   CURLMsg *msg;
    116   long L;
    117   unsigned int C=0;
    118   int M, Q, U = -1;
    119   fd_set R, W, E;
    120   struct timeval T;
    121 
    122   curl_global_init(CURL_GLOBAL_ALL);
    123 
    124   cm = curl_multi_init();
    125 
    126   /* we can optionally limit the total amount of connections this multi handle
    127      uses */
    128   curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX);
    129 
    130   for(C = 0; C < MAX; ++C) {
    131     init(cm, C);
    132   }
    133 
    134   while(U) {
    135     curl_multi_perform(cm, &U);
    136 
    137     if(U) {
    138       FD_ZERO(&R);
    139       FD_ZERO(&W);
    140       FD_ZERO(&E);
    141 
    142       if(curl_multi_fdset(cm, &R, &W, &E, &M)) {
    143         fprintf(stderr, "E: curl_multi_fdset\n");
    144         return EXIT_FAILURE;
    145       }
    146 
    147       if(curl_multi_timeout(cm, &L)) {
    148         fprintf(stderr, "E: curl_multi_timeout\n");
    149         return EXIT_FAILURE;
    150       }
    151       if(L == -1)
    152         L = 100;
    153 
    154       if(M == -1) {
    155 #ifdef WIN32
    156         Sleep(L);
    157 #else
    158         sleep((unsigned int)L / 1000);
    159 #endif
    160       }
    161       else {
    162         T.tv_sec = L/1000;
    163         T.tv_usec = (L%1000)*1000;
    164 
    165         if(0 > select(M+1, &R, &W, &E, &T)) {
    166           fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n",
    167               M+1, L, errno, strerror(errno));
    168           return EXIT_FAILURE;
    169         }
    170       }
    171     }
    172 
    173     while((msg = curl_multi_info_read(cm, &Q))) {
    174       if(msg->msg == CURLMSG_DONE) {
    175         char *url;
    176         CURL *e = msg->easy_handle;
    177         curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);
    178         fprintf(stderr, "R: %d - %s <%s>\n",
    179                 msg->data.result, curl_easy_strerror(msg->data.result), url);
    180         curl_multi_remove_handle(cm, e);
    181         curl_easy_cleanup(e);
    182       }
    183       else {
    184         fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
    185       }
    186       if(C < CNT) {
    187         init(cm, C++);
    188         U++; /* just to prevent it from remaining at 0 if there are more
    189                 URLs to get */
    190       }
    191     }
    192   }
    193 
    194   curl_multi_cleanup(cm);
    195   curl_global_cleanup();
    196 
    197   return EXIT_SUCCESS;
    198 }
    199