天天看点

libcurl的实用例子

官方的例子:

https://curl.haxx.se/libcurl/c/example.html

事实上我们集成使用时希望

1.非阻塞,方便随时取消

2.看到进度

3.逐个下载

其他的暂时没啥叼用。

融合官网例子,自己做的测试代码如下,改改封装可用了:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#ifdef _WIN32
#define WAITMS(x) Sleep(x)
#else
/* Portable sleep for platforms other than Windows. */
#define WAITMS(x)                               \ 
struct timeval wait = { 0, (x) * 1000 };      \
	(void)select(0, NULL, NULL, NULL, &wait);
#endif


#define HTTPURL "http://abc.efg.com/ddd.php"

struct MemoryStruct {
	char *memory;
	size_t size;
	size_t length;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
	printf("WriteMemoryCallback\n");
	size_t realsize = size * nmemb;
	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
	size_t totolsize = realsize + mem->size;

	if (mem->length < totolsize) {
		char *ptr = (char*)realloc(mem->memory, totolsize);
		if (ptr == NULL) {
			/* out of memory! */
			printf("not enough memory (realloc returned NULL)\n");
			return 0;
		}

		mem->memory = ptr;
	}
	
	memcpy(&(mem->memory[mem->size]), contents, realsize);
	mem->size = totolsize;
	//mem->memory[mem->size] = 0;

	return realsize;
}

#define TIME_IN_US 1  
#define TIMETYPE curl_off_t
#define TIMEOPT CURLINFO_TOTAL_TIME_T
#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL     3000000

#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES         600000000

struct myprogress {
	TIMETYPE lastruntime; /* type depends on version, see above */
	CURL *curl;
};

/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
static int xferinfo(void *p,
	curl_off_t dltotal, curl_off_t dlnow,
	curl_off_t ultotal, curl_off_t ulnow)
{

	//printf("xferinfo\n");

	struct myprogress *myp = (struct myprogress *)p;
	CURL *curl = myp->curl;
	TIMETYPE curtime = 0;

	curl_easy_getinfo(curl, TIMEOPT, &curtime);

	/* under certain circumstances it may be desirable for certain functionality
	to only run every N seconds, in order to do this the transaction time can
	be used */
	if ((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
		myp->lastruntime = curtime;
#ifdef TIME_IN_US
		fprintf(stderr, "TOTAL TIME: %" CURL_FORMAT_CURL_OFF_T ".%06ld\r\n",
			(curtime / 1000000), (long)(curtime % 1000000));
#else
		fprintf(stderr, "TOTAL TIME: %f \r\n", curtime);
#endif
	}

	fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
		"  DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
		"\r\n",
		ulnow, ultotal, dlnow, dltotal);

	if (dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
		return 1;
	return 0;
}

#define INIT_SIZE (1024*1024)

/*
* Simply download a HTTP file.
*/
int main(void)
{
	CURL *http_handle;
	CURLM *multi_handle;

	int still_running = 0; /* keep number of running handles */
	int repeats = 0;

	struct MemoryStruct chunk;

	chunk.memory = (char*)malloc(INIT_SIZE);  /* will be grown as needed by the realloc above */
	chunk.size = 0;    /* no data at this point */
	chunk.length = INIT_SIZE;

	curl_global_init(CURL_GLOBAL_DEFAULT);

	http_handle = curl_easy_init();

	/* set the options (I left out a few, you'll get the point anyway) */
	curl_easy_setopt(http_handle, CURLOPT_URL, HTTPURL);

	/* some servers don't like requests that are made without a user-agent
	field, so we provide one */
	curl_easy_setopt(http_handle, CURLOPT_USERAGENT, "live95xiu");

	/* send all data to this function  */
	curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

	/* we pass our 'chunk' struct to the callback function */
	curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, (void *)&chunk);


	struct myprogress prog;
	prog.lastruntime = 0;
	prog.curl = http_handle;
	curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, xferinfo);
	/* pass the struct pointer into the xferinfo function, note that this is
	an alias to CURLOPT_PROGRESSDATA */
	curl_easy_setopt(http_handle, CURLOPT_XFERINFODATA, &prog);
	curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L);

	/* init a multi stack */
	multi_handle = curl_multi_init();

	/* add the individual transfers */
	curl_multi_add_handle(multi_handle, http_handle);

	/* we start some action by calling perform right away */
	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" */
		mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);

		if (mc != CURLM_OK) {
			fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
			break;
		}

		/* 'numfds' being zero means either a timeout or no file descriptors to
		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_easy_cleanup(http_handle);

	curl_multi_cleanup(multi_handle);

	curl_global_cleanup();


	FILE *savefile;

	/* open the file */
	errno_t err = fopen_s(&savefile,"savefile", "wb");

	size_t written = fwrite(chunk.memory, 1, chunk.size, (FILE *)savefile);

	/* close the header file */
	fclose(savefile);

	free(chunk.memory);

	return 0;
}


           

继续阅读