10-at-a-time.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*****************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * $Id$
  9. *
  10. * Example application source code using the multi interface to download many
  11. * files, but with a capped maximum amount of simultaneous transfers.
  12. *
  13. * Written by Michael Wallner
  14. */
  15. #include <errno.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #ifndef WIN32
  19. # include <unistd.h>
  20. #endif
  21. #include <curl/multi.h>
  22. static const char *urls[] = {
  23. "http://www.microsoft.com",
  24. "http://www.opensource.org",
  25. "http://www.google.com",
  26. "http://www.yahoo.com",
  27. "http://www.ibm.com",
  28. "http://www.mysql.com",
  29. "http://www.oracle.com",
  30. "http://www.ripe.net",
  31. "http://www.iana.org",
  32. "http://www.amazon.com",
  33. "http://www.netcraft.com",
  34. "http://www.heise.de",
  35. "http://www.chip.de",
  36. "http://www.ca.com",
  37. "http://www.cnet.com",
  38. "http://www.news.com",
  39. "http://www.cnn.com",
  40. "http://www.wikipedia.org",
  41. "http://www.dell.com",
  42. "http://www.hp.com",
  43. "http://www.cert.org",
  44. "http://www.mit.edu",
  45. "http://www.nist.gov",
  46. "http://www.ebay.com",
  47. "http://www.playstation.com",
  48. "http://www.uefa.com",
  49. "http://www.ieee.org",
  50. "http://www.apple.com",
  51. "http://www.sony.com",
  52. "http://www.symantec.com",
  53. "http://www.zdnet.com",
  54. "http://www.fujitsu.com",
  55. "http://www.supermicro.com",
  56. "http://www.hotmail.com",
  57. "http://www.ecma.com",
  58. "http://www.bbc.co.uk",
  59. "http://news.google.com",
  60. "http://www.foxnews.com",
  61. "http://www.msn.com",
  62. "http://www.wired.com",
  63. "http://www.sky.com",
  64. "http://www.usatoday.com",
  65. "http://www.cbs.com",
  66. "http://www.nbc.com",
  67. "http://slashdot.org",
  68. "http://www.bloglines.com",
  69. "http://www.techweb.com",
  70. "http://www.newslink.org",
  71. "http://www.un.org",
  72. };
  73. #define MAX 10 /* number of simultaneous transfers */
  74. #define CNT sizeof(urls)/sizeof(char*) /* total number of transfers to do */
  75. static size_t cb(char *d, size_t n, size_t l, void *p)
  76. {
  77. /* take care of the data here, ignored in this example */
  78. (void)d;
  79. (void)p;
  80. return n*l;
  81. }
  82. static void init(CURLM *cm, int i)
  83. {
  84. CURL *eh = curl_easy_init();
  85. curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, cb);
  86. curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
  87. curl_easy_setopt(eh, CURLOPT_URL, urls[i]);
  88. curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]);
  89. curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
  90. curl_multi_add_handle(cm, eh);
  91. }
  92. int main(void)
  93. {
  94. CURLM *cm;
  95. CURLMsg *msg;
  96. long L;
  97. unsigned int C=0;
  98. int M, Q, U = -1;
  99. fd_set R, W, E;
  100. struct timeval T;
  101. curl_global_init(CURL_GLOBAL_ALL);
  102. cm = curl_multi_init();
  103. /* we can optionally limit the total amount of connections this multi handle
  104. uses */
  105. curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, MAX);
  106. for (C = 0; C < MAX; ++C) {
  107. init(cm, C);
  108. }
  109. while (U) {
  110. while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(cm, &U));
  111. if (U) {
  112. FD_ZERO(&R);
  113. FD_ZERO(&W);
  114. FD_ZERO(&E);
  115. if (curl_multi_fdset(cm, &R, &W, &E, &M)) {
  116. fprintf(stderr, "E: curl_multi_fdset\n");
  117. return EXIT_FAILURE;
  118. }
  119. if (curl_multi_timeout(cm, &L)) {
  120. fprintf(stderr, "E: curl_multi_timeout\n");
  121. return EXIT_FAILURE;
  122. }
  123. if (L == -1)
  124. L = 100;
  125. if (M == -1) {
  126. #ifdef WIN32
  127. Sleep(L);
  128. #else
  129. sleep(L / 1000);
  130. #endif
  131. } else {
  132. T.tv_sec = L/1000;
  133. T.tv_usec = (L%1000)*1000;
  134. if (0 > select(M+1, &R, &W, &E, &T)) {
  135. fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n",
  136. M+1, L, errno, strerror(errno));
  137. return EXIT_FAILURE;
  138. }
  139. }
  140. }
  141. while ((msg = curl_multi_info_read(cm, &Q))) {
  142. if (msg->msg == CURLMSG_DONE) {
  143. char *url;
  144. CURL *e = msg->easy_handle;
  145. curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);
  146. fprintf(stderr, "R: %d - %s <%s>\n",
  147. msg->data.result, curl_easy_strerror(msg->data.result), url);
  148. curl_multi_remove_handle(cm, e);
  149. curl_easy_cleanup(e);
  150. }
  151. else {
  152. fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
  153. }
  154. if (C < CNT) {
  155. init(cm, C++);
  156. U++; /* just to prevent it from remaining at 0 if there are more
  157. URLs to get */
  158. }
  159. }
  160. }
  161. curl_multi_cleanup(cm);
  162. curl_global_cleanup();
  163. return EXIT_SUCCESS;
  164. }