docs/examples: use curl_multi_poll() in multi examples
The API is soon two years old and deserves being shown as the primary way to drive multi code as it makes it much easier to write code. multi-poll: removed multi-legacy: add to show how we did multi API use before curl_multi_wait/poll. Closes #7352
This commit is contained in:
parent
738fb63e61
commit
ae8e11ed5f
@ -74,7 +74,7 @@ check_PROGRAMS = \
|
|||||||
multi-debugcallback \
|
multi-debugcallback \
|
||||||
multi-double \
|
multi-double \
|
||||||
multi-formadd \
|
multi-formadd \
|
||||||
multi-poll \
|
multi-legacy \
|
||||||
multi-post \
|
multi-post \
|
||||||
multi-single \
|
multi-single \
|
||||||
parseurl \
|
parseurl \
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -212,79 +212,16 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
do {
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
if(still_running)
|
||||||
struct timeval timeout;
|
/* wait for activity, timeout or "nothing" */
|
||||||
int rc; /* select() return code */
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(mc)
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
} while(still_running);
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < num_transfers; i++) {
|
for(i = 0; i < num_transfers; i++) {
|
||||||
curl_multi_remove_handle(multi_handle, trans[i].easy);
|
curl_multi_remove_handle(multi_handle, trans[i].easy);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -213,7 +213,6 @@ int main(void)
|
|||||||
{
|
{
|
||||||
CURL *easy;
|
CURL *easy;
|
||||||
CURLM *multi_handle;
|
CURLM *multi_handle;
|
||||||
int still_running; /* keep number of running handles */
|
|
||||||
int transfers = 1; /* we start with one */
|
int transfers = 1; /* we start with one */
|
||||||
struct CURLMsg *m;
|
struct CURLMsg *m;
|
||||||
|
|
||||||
@ -235,78 +234,16 @@ int main(void)
|
|||||||
curl_multi_setopt(multi_handle, CURLMOPT_PUSHFUNCTION, server_push_callback);
|
curl_multi_setopt(multi_handle, CURLMOPT_PUSHFUNCTION, server_push_callback);
|
||||||
curl_multi_setopt(multi_handle, CURLMOPT_PUSHDATA, &transfers);
|
curl_multi_setopt(multi_handle, CURLMOPT_PUSHDATA, &transfers);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct timeval timeout;
|
int still_running; /* keep number of running handles */
|
||||||
int rc; /* select() return code */
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(still_running)
|
||||||
fd_set fdwrite;
|
/* wait for activity, timeout or "nothing" */
|
||||||
fd_set fdexcep;
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
if(mc)
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A little caution when doing server push is that libcurl itself has
|
* A little caution when doing server push is that libcurl itself has
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -279,79 +279,17 @@ int main(int argc, char **argv)
|
|||||||
/* We do HTTP/2 so let's stick to one connection per host */
|
/* We do HTTP/2 so let's stick to one connection per host */
|
||||||
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);
|
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
do {
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
if(still_running)
|
||||||
struct timeval timeout;
|
/* wait for activity, timeout or "nothing" */
|
||||||
int rc; /* select() return code */
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(mc)
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
} while(still_running);
|
||||||
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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -32,35 +32,13 @@
|
|||||||
/* This is a simple example showing how to fetch mail using libcurl's IMAP
|
/* This is a simple example showing how to fetch mail using libcurl's IMAP
|
||||||
* capabilities. It builds on the imap-fetch.c example to demonstrate how to
|
* capabilities. It builds on the imap-fetch.c example to demonstrate how to
|
||||||
* use libcurl's multi interface.
|
* use libcurl's multi interface.
|
||||||
*
|
|
||||||
* Note that this example requires libcurl 7.30.0 or above.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
|
|
||||||
|
|
||||||
static struct timeval tvnow(void)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
/* time() returns the value of time in seconds since the epoch */
|
|
||||||
now.tv_sec = (long)time(NULL);
|
|
||||||
now.tv_usec = 0;
|
|
||||||
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long tvdiff(struct timeval newer, struct timeval older)
|
|
||||||
{
|
|
||||||
return (newer.tv_sec - older.tv_sec) * 1000 +
|
|
||||||
(newer.tv_usec - older.tv_usec) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLM *mcurl;
|
CURLM *mcurl;
|
||||||
int still_running = 1;
|
int still_running = 1;
|
||||||
struct timeval mp_start;
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
@ -82,86 +60,16 @@ int main(void)
|
|||||||
/* Tell the multi stack about our easy handle */
|
/* Tell the multi stack about our easy handle */
|
||||||
curl_multi_add_handle(mcurl, curl);
|
curl_multi_add_handle(mcurl, curl);
|
||||||
|
|
||||||
/* Record the start time which we can use later */
|
do {
|
||||||
mp_start = tvnow();
|
CURLMcode mc = curl_multi_perform(mcurl, &still_running);
|
||||||
|
|
||||||
/* We start some action by calling perform right away */
|
if(still_running)
|
||||||
curl_multi_perform(mcurl, &still_running);
|
/* wait for activity, timeout or "nothing" */
|
||||||
|
mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL);
|
||||||
|
|
||||||
while(still_running) {
|
if(mc)
|
||||||
struct timeval timeout;
|
|
||||||
fd_set fdread;
|
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
int rc;
|
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
/* Initialise the file descriptors */
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* Set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(mcurl, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 1)
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
else
|
|
||||||
timeout.tv_usec = (curl_timeo % 1000) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get file descriptors from the transfers */
|
|
||||||
mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
} while(still_running);
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ABORTING: Since it seems that we would have run forever.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1: /* select error */
|
|
||||||
break;
|
|
||||||
case 0: /* timeout */
|
|
||||||
default: /* action */
|
|
||||||
curl_multi_perform(mcurl, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always cleanup */
|
/* Always cleanup */
|
||||||
curl_multi_remove_handle(mcurl, curl);
|
curl_multi_remove_handle(mcurl, curl);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -48,7 +48,7 @@ int main(void)
|
|||||||
CURL *handles[HANDLECOUNT];
|
CURL *handles[HANDLECOUNT];
|
||||||
CURLM *multi_handle;
|
CURLM *multi_handle;
|
||||||
|
|
||||||
int still_running = 0; /* keep number of running handles */
|
int still_running = 1; /* keep number of running handles */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
CURLMsg *msg; /* for picking up messages with the transfer status */
|
CURLMsg *msg; /* for picking up messages with the transfer status */
|
||||||
@ -71,79 +71,16 @@ int main(void)
|
|||||||
for(i = 0; i<HANDLECOUNT; i++)
|
for(i = 0; i<HANDLECOUNT; i++)
|
||||||
curl_multi_add_handle(multi_handle, handles[i]);
|
curl_multi_add_handle(multi_handle, handles[i]);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
|
|
||||||
while(still_running) {
|
while(still_running) {
|
||||||
struct timeval timeout;
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
int rc; /* select() return code */
|
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(still_running)
|
||||||
fd_set fdwrite;
|
/* wait for activity, timeout or "nothing" */
|
||||||
fd_set fdexcep;
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
if(mc)
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0: /* timeout */
|
|
||||||
default: /* action */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See how the transfers went */
|
/* See how the transfers went */
|
||||||
while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
|
while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
|
||||||
if(msg->msg == CURLMSG_DONE) {
|
if(msg->msg == CURLMSG_DONE) {
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -147,81 +147,17 @@ int main(void)
|
|||||||
/* add the individual transfers */
|
/* add the individual transfers */
|
||||||
curl_multi_add_handle(multi_handle, http_handle);
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
do {
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
if(still_running)
|
||||||
struct timeval timeout;
|
/* wait for activity, timeout or "nothing" */
|
||||||
int rc; /* select() return code */
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(mc)
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
} while(still_running);
|
||||||
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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
still_running = 0;
|
|
||||||
printf("select() returns error, this is badness\n");
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -42,7 +42,7 @@ int main(void)
|
|||||||
CURL *http_handle2;
|
CURL *http_handle2;
|
||||||
CURLM *multi_handle;
|
CURLM *multi_handle;
|
||||||
|
|
||||||
int still_running = 0; /* keep number of running handles */
|
int still_running = 1; /* keep number of running handles */
|
||||||
|
|
||||||
http_handle = curl_easy_init();
|
http_handle = curl_easy_init();
|
||||||
http_handle2 = curl_easy_init();
|
http_handle2 = curl_easy_init();
|
||||||
@ -60,80 +60,32 @@ int main(void)
|
|||||||
curl_multi_add_handle(multi_handle, http_handle);
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
curl_multi_add_handle(multi_handle, http_handle2);
|
curl_multi_add_handle(multi_handle, http_handle2);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
|
|
||||||
while(still_running) {
|
while(still_running) {
|
||||||
struct timeval timeout;
|
CURLMsg *msg;
|
||||||
int rc; /* select() return code */
|
int queued;
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
fd_set fdread;
|
if(still_running)
|
||||||
fd_set fdwrite;
|
/* wait for activity, timeout or "nothing" */
|
||||||
fd_set fdexcep;
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
if(mc)
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
do {
|
||||||
select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
|
msg = curl_multi_info_read(multi_handle, &queued);
|
||||||
no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
|
if(msg) {
|
||||||
to sleep 100ms, which is the minimum suggested value in the
|
if(msg->msg == CURLMSG_DONE) {
|
||||||
curl_multi_fdset() doc. */
|
/* a transfer ended */
|
||||||
|
fprintf(stderr, "Transfer completed\n");
|
||||||
if(maxfd == -1) {
|
}
|
||||||
#ifdef _WIN32
|
}
|
||||||
Sleep(100);
|
} while(msg);
|
||||||
rc = 0;
|
|
||||||
#else
|
|
||||||
/* Portable sleep for platforms other than Windows. */
|
|
||||||
struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
|
|
||||||
rc = select(0, NULL, NULL, NULL, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curl_multi_remove_handle(multi_handle, http_handle);
|
||||||
|
curl_multi_remove_handle(multi_handle, http_handle2);
|
||||||
|
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
curl_easy_cleanup(http_handle);
|
curl_easy_cleanup(http_handle);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -81,80 +81,17 @@ int main(void)
|
|||||||
|
|
||||||
curl_multi_add_handle(multi_handle, curl);
|
curl_multi_add_handle(multi_handle, curl);
|
||||||
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
do {
|
||||||
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
if(still_running)
|
||||||
struct timeval timeout;
|
/* wait for activity, timeout or "nothing" */
|
||||||
int rc; /* select() return code */
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(mc)
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
} while(still_running);
|
||||||
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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
printf("perform!\n");
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
printf("running: %d!\n", still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
|||||||
177
docs/examples/multi-legacy.c
Normal file
177
docs/examples/multi-legacy.c
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at https://curl.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
/* <DESC>
|
||||||
|
* A basic application source code using the multi interface doing two
|
||||||
|
* transfers in parallel without curl_multi_wait/poll.
|
||||||
|
* </DESC>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* somewhat unix-specific */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* curl stuff */
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Download a HTTP file and upload an FTP file simultaneously.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HANDLECOUNT 2 /* Number of simultaneous transfers */
|
||||||
|
#define HTTP_HANDLE 0 /* Index for the HTTP transfer */
|
||||||
|
#define FTP_HANDLE 1 /* Index for the FTP transfer */
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *handles[HANDLECOUNT];
|
||||||
|
CURLM *multi_handle;
|
||||||
|
|
||||||
|
int still_running = 0; /* keep number of running handles */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
CURLMsg *msg; /* for picking up messages with the transfer status */
|
||||||
|
int msgs_left; /* how many messages are left */
|
||||||
|
|
||||||
|
/* Allocate one CURL handle per transfer */
|
||||||
|
for(i = 0; i<HANDLECOUNT; i++)
|
||||||
|
handles[i] = curl_easy_init();
|
||||||
|
|
||||||
|
/* set the options (I left out a few, you'll get the point anyway) */
|
||||||
|
curl_easy_setopt(handles[HTTP_HANDLE], CURLOPT_URL, "https://example.com");
|
||||||
|
|
||||||
|
curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_URL, "ftp://example.com");
|
||||||
|
curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_UPLOAD, 1L);
|
||||||
|
|
||||||
|
/* init a multi stack */
|
||||||
|
multi_handle = curl_multi_init();
|
||||||
|
|
||||||
|
/* add the individual transfers */
|
||||||
|
for(i = 0; i<HANDLECOUNT; i++)
|
||||||
|
curl_multi_add_handle(multi_handle, handles[i]);
|
||||||
|
|
||||||
|
/* we start some action by calling perform right away */
|
||||||
|
curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
|
while(still_running) {
|
||||||
|
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(&fdread);
|
||||||
|
FD_ZERO(&fdwrite);
|
||||||
|
FD_ZERO(&fdexcep);
|
||||||
|
|
||||||
|
/* set a suitable timeout to play around with */
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
curl_multi_timeout(multi_handle, &curl_timeo);
|
||||||
|
if(curl_timeo >= 0) {
|
||||||
|
timeout.tv_sec = curl_timeo / 1000;
|
||||||
|
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &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 >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(rc) {
|
||||||
|
case -1:
|
||||||
|
/* select error */
|
||||||
|
break;
|
||||||
|
case 0: /* timeout */
|
||||||
|
default: /* action */
|
||||||
|
curl_multi_perform(multi_handle, &still_running);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See how the transfers went */
|
||||||
|
while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
|
||||||
|
if(msg->msg == CURLMSG_DONE) {
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
/* Find out which handle this message is about */
|
||||||
|
for(idx = 0; idx<HANDLECOUNT; idx++) {
|
||||||
|
int found = (msg->easy_handle == handles[idx]);
|
||||||
|
if(found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(idx) {
|
||||||
|
case HTTP_HANDLE:
|
||||||
|
printf("HTTP transfer completed with status %d\n", msg->data.result);
|
||||||
|
break;
|
||||||
|
case FTP_HANDLE:
|
||||||
|
printf("FTP transfer completed with status %d\n", msg->data.result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
/* Free the CURL handles */
|
||||||
|
for(i = 0; i<HANDLECOUNT; i++)
|
||||||
|
curl_easy_cleanup(handles[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,76 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* _ _ ____ _
|
|
||||||
* Project ___| | | | _ \| |
|
|
||||||
* / __| | | | |_) | |
|
|
||||||
* | (__| |_| | _ <| |___
|
|
||||||
* \___|\___/|_| \_\_____|
|
|
||||||
*
|
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
||||||
*
|
|
||||||
* This software is licensed as described in the file COPYING, which
|
|
||||||
* you should have received as part of this distribution. The terms
|
|
||||||
* are also available at https://curl.se/docs/copyright.html.
|
|
||||||
*
|
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
||||||
* copies of the Software, and permit persons to whom the Software is
|
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
|
||||||
/* <DESC>
|
|
||||||
* single download with the multi interface's curl_multi_poll
|
|
||||||
* </DESC>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* somewhat unix-specific */
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/* curl stuff */
|
|
||||||
#include <curl/curl.h>
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
CURL *http_handle;
|
|
||||||
CURLM *multi_handle;
|
|
||||||
int still_running = 1; /* keep number of running handles */
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
||||||
|
|
||||||
http_handle = curl_easy_init();
|
|
||||||
|
|
||||||
curl_easy_setopt(http_handle, CURLOPT_URL, "https://www.example.com/");
|
|
||||||
|
|
||||||
multi_handle = curl_multi_init();
|
|
||||||
|
|
||||||
curl_multi_add_handle(multi_handle, http_handle);
|
|
||||||
|
|
||||||
while(still_running) {
|
|
||||||
CURLMcode mc; /* curl_multi_poll() return code */
|
|
||||||
int numfds;
|
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
|
||||||
mc = curl_multi_perform(multi_handle, &still_running);
|
|
||||||
|
|
||||||
if(still_running)
|
|
||||||
/* wait for activity, timeout or "nothing" */
|
|
||||||
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, &numfds);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_remove_handle(multi_handle, http_handle);
|
|
||||||
curl_easy_cleanup(http_handle);
|
|
||||||
curl_multi_cleanup(multi_handle);
|
|
||||||
curl_global_cleanup();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -77,80 +77,16 @@ int main(void)
|
|||||||
|
|
||||||
curl_multi_add_handle(multi_handle, curl);
|
curl_multi_add_handle(multi_handle, curl);
|
||||||
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
do {
|
||||||
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
if(still_running)
|
||||||
struct timeval timeout;
|
/* wait for activity, timeout or "nothing" */
|
||||||
int rc; /* select() return code */
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
fd_set fdread;
|
if(mc)
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 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, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
} while(still_running);
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1:
|
|
||||||
/* select error */
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* timeout or readable/writable sockets */
|
|
||||||
printf("perform!\n");
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
printf("running: %d!\n", still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -50,9 +50,7 @@ int main(void)
|
|||||||
{
|
{
|
||||||
CURL *http_handle;
|
CURL *http_handle;
|
||||||
CURLM *multi_handle;
|
CURLM *multi_handle;
|
||||||
|
int still_running = 1; /* keep number of running handles */
|
||||||
int still_running = 0; /* keep number of running handles */
|
|
||||||
int repeats = 0;
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
@ -67,37 +65,18 @@ int main(void)
|
|||||||
/* add the individual transfers */
|
/* add the individual transfers */
|
||||||
curl_multi_add_handle(multi_handle, http_handle);
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
|
||||||
/* we start some action by calling perform right away */
|
do {
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
|
||||||
|
|
||||||
while(still_running) {
|
|
||||||
CURLMcode mc; /* curl_multi_wait() return code */
|
|
||||||
int numfds;
|
|
||||||
|
|
||||||
/* wait for activity, timeout or "nothing" */
|
/* wait for activity, timeout or "nothing" */
|
||||||
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
|
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
if(mc != CURLM_OK) {
|
||||||
fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
|
fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'numfds' being zero means either a timeout or no file descriptors to
|
} while(still_running);
|
||||||
wait for. Try timeout on first occurrence, then assume no file
|
|
||||||
descriptors and no file descriptors to wait for means wait for 100
|
|
||||||
milliseconds. */
|
|
||||||
|
|
||||||
if(!numfds) {
|
|
||||||
repeats++; /* count number of repeated zero numfds */
|
|
||||||
if(repeats > 1) {
|
|
||||||
WAITMS(100); /* sleep 100 milliseconds */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
repeats = 0;
|
|
||||||
|
|
||||||
curl_multi_perform(multi_handle, &still_running);
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_remove_handle(multi_handle, http_handle);
|
curl_multi_remove_handle(multi_handle, http_handle);
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -32,35 +32,13 @@
|
|||||||
/* This is a simple example showing how to retrieve mail using libcurl's POP3
|
/* This is a simple example showing how to retrieve mail using libcurl's POP3
|
||||||
* capabilities. It builds on the pop3-retr.c example to demonstrate how to use
|
* capabilities. It builds on the pop3-retr.c example to demonstrate how to use
|
||||||
* libcurl's multi interface.
|
* libcurl's multi interface.
|
||||||
*
|
|
||||||
* Note that this example requires libcurl 7.20.0 or above.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
|
|
||||||
|
|
||||||
static struct timeval tvnow(void)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
/* time() returns the value of time in seconds since the epoch */
|
|
||||||
now.tv_sec = (long)time(NULL);
|
|
||||||
now.tv_usec = 0;
|
|
||||||
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long tvdiff(struct timeval newer, struct timeval older)
|
|
||||||
{
|
|
||||||
return (newer.tv_sec - older.tv_sec) * 1000 +
|
|
||||||
(newer.tv_usec - older.tv_usec) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLM *mcurl;
|
CURLM *mcurl;
|
||||||
int still_running = 1;
|
int still_running = 1;
|
||||||
struct timeval mp_start;
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
@ -82,86 +60,17 @@ int main(void)
|
|||||||
/* Tell the multi stack about our easy handle */
|
/* Tell the multi stack about our easy handle */
|
||||||
curl_multi_add_handle(mcurl, curl);
|
curl_multi_add_handle(mcurl, curl);
|
||||||
|
|
||||||
/* Record the start time which we can use later */
|
do {
|
||||||
mp_start = tvnow();
|
CURLMcode mc = curl_multi_perform(mcurl, &still_running);
|
||||||
|
|
||||||
/* We start some action by calling perform right away */
|
if(still_running)
|
||||||
curl_multi_perform(mcurl, &still_running);
|
/* wait for activity, timeout or "nothing" */
|
||||||
|
mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL);
|
||||||
|
|
||||||
while(still_running) {
|
if(mc)
|
||||||
struct timeval timeout;
|
|
||||||
fd_set fdread;
|
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
int rc;
|
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
/* Initialise the file descriptors */
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* Set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(mcurl, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 1)
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
else
|
|
||||||
timeout.tv_usec = (curl_timeo % 1000) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get file descriptors from the transfers */
|
|
||||||
mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
} while(still_running);
|
||||||
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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ABORTING: Since it seems that we would have run forever.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1: /* select error */
|
|
||||||
break;
|
|
||||||
case 0: /* timeout */
|
|
||||||
default: /* action */
|
|
||||||
curl_multi_perform(mcurl, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always cleanup */
|
/* Always cleanup */
|
||||||
curl_multi_remove_handle(mcurl, curl);
|
curl_multi_remove_handle(mcurl, curl);
|
||||||
|
|||||||
@ -31,16 +31,12 @@
|
|||||||
/* This is an example showing how to send mail using libcurl's SMTP
|
/* This is an example showing how to send mail using libcurl's SMTP
|
||||||
* capabilities. It builds on the smtp-mail.c example to demonstrate how to use
|
* capabilities. It builds on the smtp-mail.c example to demonstrate how to use
|
||||||
* libcurl's multi interface.
|
* libcurl's multi interface.
|
||||||
*
|
|
||||||
* Note that this example requires libcurl 7.20.0 or above.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FROM_MAIL "<sender@example.com>"
|
#define FROM_MAIL "<sender@example.com>"
|
||||||
#define TO_MAIL "<recipient@example.com>"
|
#define TO_MAIL "<recipient@example.com>"
|
||||||
#define CC_MAIL "<info@example.com>"
|
#define CC_MAIL "<info@example.com>"
|
||||||
|
|
||||||
#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
|
|
||||||
|
|
||||||
static const char *payload_text =
|
static const char *payload_text =
|
||||||
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
|
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
|
||||||
"To: " TO_MAIL "\r\n"
|
"To: " TO_MAIL "\r\n"
|
||||||
@ -84,29 +80,11 @@ static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timeval tvnow(void)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
/* time() returns the value of time in seconds since the epoch */
|
|
||||||
now.tv_sec = (long)time(NULL);
|
|
||||||
now.tv_usec = 0;
|
|
||||||
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long tvdiff(struct timeval newer, struct timeval older)
|
|
||||||
{
|
|
||||||
return (newer.tv_sec - older.tv_sec) * 1000 +
|
|
||||||
(newer.tv_usec - older.tv_usec) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLM *mcurl;
|
CURLM *mcurl;
|
||||||
int still_running = 1;
|
int still_running = 1;
|
||||||
struct timeval mp_start;
|
|
||||||
struct curl_slist *recipients = NULL;
|
struct curl_slist *recipients = NULL;
|
||||||
struct upload_status upload_ctx = { 0 };
|
struct upload_status upload_ctx = { 0 };
|
||||||
|
|
||||||
@ -148,86 +126,17 @@ int main(void)
|
|||||||
/* Tell the multi stack about our easy handle */
|
/* Tell the multi stack about our easy handle */
|
||||||
curl_multi_add_handle(mcurl, curl);
|
curl_multi_add_handle(mcurl, curl);
|
||||||
|
|
||||||
/* Record the start time which we can use later */
|
do {
|
||||||
mp_start = tvnow();
|
CURLMcode mc = curl_multi_perform(mcurl, &still_running);
|
||||||
|
|
||||||
/* We start some action by calling perform right away */
|
if(still_running)
|
||||||
curl_multi_perform(mcurl, &still_running);
|
/* wait for activity, timeout or "nothing" */
|
||||||
|
mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL);
|
||||||
|
|
||||||
while(still_running) {
|
if(mc)
|
||||||
struct timeval timeout;
|
|
||||||
fd_set fdread;
|
|
||||||
fd_set fdwrite;
|
|
||||||
fd_set fdexcep;
|
|
||||||
int maxfd = -1;
|
|
||||||
int rc;
|
|
||||||
CURLMcode mc; /* curl_multi_fdset() return code */
|
|
||||||
|
|
||||||
long curl_timeo = -1;
|
|
||||||
|
|
||||||
/* Initialise the file descriptors */
|
|
||||||
FD_ZERO(&fdread);
|
|
||||||
FD_ZERO(&fdwrite);
|
|
||||||
FD_ZERO(&fdexcep);
|
|
||||||
|
|
||||||
/* Set a suitable timeout to play around with */
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
curl_multi_timeout(mcurl, &curl_timeo);
|
|
||||||
if(curl_timeo >= 0) {
|
|
||||||
timeout.tv_sec = curl_timeo / 1000;
|
|
||||||
if(timeout.tv_sec > 1)
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
else
|
|
||||||
timeout.tv_usec = (curl_timeo % 1000) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get file descriptors from the transfers */
|
|
||||||
mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
|
|
||||||
|
|
||||||
if(mc != CURLM_OK) {
|
|
||||||
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* On success the value of maxfd is guaranteed to be >= -1. We call
|
} while(still_running);
|
||||||
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, &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, &fdread, &fdwrite, &fdexcep, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ABORTING: Since it seems that we would have run forever.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(rc) {
|
|
||||||
case -1: /* select error */
|
|
||||||
break;
|
|
||||||
case 0: /* timeout */
|
|
||||||
default: /* action */
|
|
||||||
curl_multi_perform(mcurl, &still_running);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the list of recipients */
|
/* Free the list of recipients */
|
||||||
curl_slist_free_all(recipients);
|
curl_slist_free_all(recipients);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user