#include
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include
#include <string.h>
#include <assert.h>
#define ERROR_EXIT(x...) do {fprintf(stderr, x);fprintf(stderr, ", %s:%d", __FILE__, __LINE__);exit(-1);}while(0)
#define DEBUG(x...) do {fprintf(stdout, x);}while(0)
#define ERROR(x...) do {fprintf(stderr, x);fprintf(stderr, ", %s:%d", __FILE__, __LINE__);}while(0)
CURLM *multi_handle = NULL;
int epoll_fd = -1;
int still_running;
static void mcode_or_die(const char *where, CURLMcode code) {
if ( CURLM_OK != code ) {
const char *s;
switch (code) {
case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
case CURLM_INTERNAL_ERROR: s="CURLM_INTERNAL_ERROR"; break;
case CURLM_UNKNOWN_OPTION: s="CURLM_UNKNOWN_OPTION"; break;
case CURLM_LAST: s="CURLM_LAST"; break;
default: s="CURLM_unknown"; break;
case CURLM_BAD_SOCKET: s="CURLM_BAD_SOCKET";
ERROR("ERROR: %s returns %s\n", where, s);
return;
}
ERROR("ERROR: %s returns %s\n", where, s);
exit(code);
}
else {
}
}
static void check_multi_info() {
char *eff_url;
CURLcode res;
int msgs_left;
CURLMsg *msg;
CURL *easy;
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if (msg->msg == CURLMSG_DONE) {
easy = msg->easy_handle;
res = msg->data.result;
curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
DEBUG("DONE: %s => (%d)\n", eff_url, res);
curl_multi_remove_handle(multi_handle, easy);
curl_easy_cleanup(easy);
}
}
}
static int multi_socket_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) {
DEBUG("multi_socket_cb--------------------------------------------------------------%p\n", sockp);
struct epoll_event ee;
ee.data.fd = s;
switch ( what ) {
case CURL_POLL_REMOVE:
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, s, NULL);
DEBUG("---->>>>finish%p\n", sockp);
return 0;
case CURL_POLL_IN:
ee.events = EPOLLIN;
DEBUG("---->>>>EPOLLIN%p\n", sockp);
epoll_ctl(epoll_fd, EPOLL_CTL_MOD, s, &ee);
break;
case CURL_POLL_OUT:
ee.events = EPOLLOUT;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s, &ee);
DEBUG("---->>>>EPOLLOUT%p\n", sockp);
break;
case CURL_POLL_INOUT:
ee.events = EPOLLIN | EPOLLOUT;
DEBUG("---->>>>EPOLLINOUT%p\n", sockp);
break;
}
return 0;
}
FILE *filep = NULL;
static size_t easy_write_cb(void *ptr, size_t size, size_t nmemb, void *data) {
if ( filep == NULL ) {
filep = fopen("/tmp/a.html", "w");
assert(filep);
}
fwrite(ptr, size, nmemb, filep);
size_t realsize = size * nmemb;
DEBUG("======> size:%u\n",realsize);
return realsize;
}
int main(int argc, char **argv) {
if ( argc != 1 ) {
ERROR_EXIT("get");
}
curl_global_init(CURL_GLOBAL_ALL);
multi_handle = curl_multi_init();
if ( NULL == multi_handle ) {
ERROR_EXIT("curl_multi_init");
}
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, multi_socket_cb);
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, NULL);
epoll_fd = epoll_create(1024);
if ( -1 == epoll_fd ) {
ERROR_EXIT("epoll_create");
}
struct epoll_event ees[10];
ees[0].data.fd = 0;
ees[0].events = EPOLLIN;
if ( 0 != epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, ees) ) {
ERROR_EXIT("epoll_ctl");
}
int ret = 0;
FILE *pFlieInput = fdopen(0, "r");
char line[1024];
while ( 1 ) {
ret = epoll_wait(epoll_fd, ees, 10, 10);
for ( int i = 0;i < ret;i++ ) {
int fd = ees[i].data.fd;
if ( ees[i].data.fd == 0 ) {
fgets(line, sizeof(line), pFlieInput);
int line_len = strlen(line);
if ( line[line_len - 1] == '\n' ) {
line[line_len - 1] = 0;
}
DEBUG("url:%s\n", line);
CURL *easy_handle = curl_easy_init();
curl_easy_setopt(easy_handle, CURLOPT_URL, line);
curl_multi_add_handle(multi_handle, easy_handle);
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, easy_write_cb);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
curl_multi_socket_action(multi_handle, CURL_SOCKET_TIMEOUT,0, &still_running);
gettimeofday(&tv2, NULL);
DEBUG("duration: %u\n", (tv2.tv_sec - tv1.tv_sec)*1000000+(tv2.tv_usec - tv1.tv_usec));
}
else {
int action = (ees[i].events & EPOLLIN ? CURL_CSELECT_IN : 0) | (ees[i].events & EPOLLOUT ? CURL_CSELECT_OUT : 0);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
CURLMcode rc = curl_multi_socket_action(multi_handle, fd, action, &still_running);
gettimeofday(&tv2, NULL);
DEBUG("duration222222: %u\n", (tv2.tv_sec - tv1.tv_sec)*1000000+(tv2.tv_usec - tv1.tv_usec));
mcode_or_die("event_cb: curl_multi_socket_action", rc);
check_multi_info();
}
}
}
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return 0;
}
build:
g++ -g -Wall -o get tttt.cpp -lcurl
when i run ./get
it show following :
>./get //enter
www.microsoft.com
url:www.microsoft.com
multi_socket_cb--------------------------------------------------------------(nil)
---->>>>EPOLLIN(nil)
duration: 748
//-----------> stop at this,and when you input somthing, it continue to run.
//why ? it so wire..., i need to do some ??