libcurl主要提供了两种发送http请求的方式,分别是Easy interface方式和multi interface方式,前者是采用阻塞的方式发送单条数据,后者采用组合的方式可以一次性发送多条数据

一、Easy interface

libcurl的easy interface是最基本的用法,简要流程为:
1、在主线程中调用curl_global_init(CURL_GLOBAL_ALL)初始化
2、调用curl_easy_init获取一个句柄;
3、调用curl_easy_setopt函数设置此次传输的一些基本参数,如url地址、http头、cookie信息、发送超时时间等,其中,CURLOPT_URL是必设的选项;
4、设置完成后,调用curl_easy_perform函数发送数据;
5、数据发送完毕后,调用curl_easy_cleanup清空句柄;
6、调用curl_global_cleanup()做清理工作。

实现代码:

bool send_easy_hanler(char* post_url, req_t* req)
  //easy handler的句柄
  CURL* curl = NULL;
  CURLcode res = CURLE_OK;
  //HTTP报文头
  struct curl_slist* headers = NULL;
  char tmp_str[256] = { 0 };
  //构建HTTP报文头
  snprintf(tmp_str, sizeof(tmp_str), "User-Agent: %s", req->user_agent_);
  headers = curl_slist_append(headers, tmp_str);
  snprintf(tmp_str, sizeof(tmp_str), "Accept-Language: %s", req->language_);
  headers = curl_slist_append(headers, tmp_str);
  snprintf(tmp_str, sizeof(tmp_str), "X-FORWORDED-FOR: %s", req->ip_.c_str());
  headers = curl_slist_append(headers, tmp_str);
  /*这个函数只能用一次,如果这个函数在curl_easy_init函数调用时还没调用,
  它讲由libcurl库自动调用,所以多线程下最好在主线程中调用一次该函数以防止在线程
  中curl_easy_init时多次调用*/
  curl_global_init(CURL_GLOBAL_ALL);
  //初始化easy handler句柄
  curl = curl_easy_init();
  if (curl) {
	//设置post请求的url地址
    curl_easy_setopt(curl, CURLOPT_URL, post_url);
	//设置HTTP头
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
	//设置发送超时时间
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1);
	//执行单条请求
    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
	  //curl_easy_strerror进行出错打印
      LOG(WARNING) << "curl_easy_perform() failed:" << curl_easy_strerror(res);
    curl_slist_free_all(headers);
	//这个调用用来结束一个会话.与curl_easy_init配合着用
    curl_easy_cleanup(curl);
	//在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数
	curl_global_cleanup();

二、multi interface multi interface提供了多种easy interface没有的特性,主要是 1、提供了pull接口,使用libcurl的程序能够决定何时何处调用libcurl来get/send数据 2、在同一线程中实现多条数据同时发送,且并没有使得程序更加复杂 3、程序可以在自己的文件描述符和curl的文件描述符中同时等待执行 4、提供基于事件的处理、扩大传输规模到数千个并发连接 multi接口的使用会比easy 接口稍微复杂点,毕竟multi接口是依赖easy接口的,简要流程为: 1、使用curl_multi_init创建一个multi handle,这个handler会在后续的curl_multi_*函数中使用multi handler可以同时并发传输多条数据,每一条单独的数据是由一个easy handler创建; 2、需要事先将需要传输的所有easyhandler创建好,并使用curl_easy_setopt设置各自属性,接着调用curl_multi_add_handle函数逐个添加到multi handle中; 3、调用curl_multi_perform进程数据传输,传输过程中将会调用每一个easy handler设置的回调函数或者配置内容,程序通过函数curl_multi_fdset、select()提取信息来判断何时进行数据传输等操作,函数curl_multi_perform的一个输入参数储存仍在进行传输的数据量,通过读取该变量,可以判断multi handles是否运行完毕,传输完毕不代表传输成功,可能有一个或多个传输失败; 4、调用函数curl_multi_info_read可以获取当前或之前传输的信息,重复调用该函数直到该消息队列为空,每一条返回信息都包含对应的easl handler的传输情况; 5、当一个easy handler传输完成,此easy handler仍然仍然停留在multi stack中,需要调用curl_multi_remove_handle将其从multi stack中移除,然后调用curl_easy_cleanup将其关闭; 6、当multi stack中的所有传输都完成时,调用 curl_multi_cleanup关闭multi handler,需要注意的是事先要调用curl_easy_cleanup逐个清空所有easy handler。
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <curl/multi.h>
static const char *urls[] = {
  "http://www.microsoft.com",
  "http://www.opensource.org",
  "http://www.google.com",
  "http://www.yahoo.com",
  "http://www.ibm.com",
  "http://www.mysql.com",
  "http://www.oracle.com",
  "http://www.ripe.net",
#define MAX 8 /* number of simultaneous transfers */
#define CNT sizeof(urls)/sizeof(char*) /* total number of transfers to do */
/*此函数读取libcurl发送数据后的返回信息,如果不设置此函数,
那么返回值将会输出到控制台,影响程序性能*/
static size_t cb(char *d, size_t n, size_t l, void *p)
  /* take care of the data here, ignored in this example */
  (void)d;
  (void)p;
  return n*l;
//设置单个easy handler的属性添加单个easy handler到multi handler中,
static void init(CURLM *cm, int i)
  CURL *eh = curl_easy_init();
  curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, cb);
  curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
  curl_easy_setopt(eh, CURLOPT_URL, urls[i]);
  curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]);
  curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
  //添加easy handler 到multi handler中
  curl_multi_add_handle(cm, eh);
int main(void)
  CURLM *cm;
  CURLMsg *msg;
  long curl_timeo;
  unsigned int C=0;
  int max_fd, msgs_left, still_running = -1;//still_running判断multi handler是否传输完毕
  fd_set fd_read, fd_write, fd_except;
  struct timeval T;
  curl_global_init(CURL_GLOBAL_ALL);
  cm = curl_multi_init();
  //现在multi handler的最大连接数
  curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX);
  for(C = 0; C < MAX; ++C) {
    init(cm, C);
    curl_multi_perform(cm, &still_running);
    if(still_running) {
      FD_ZERO(&fd_read);
      FD_ZERO(&fd_write);
      FD_ZERO(&fd_except);
	  //获取multi curl需要监听的文件描述符集合 fd_set
      if(!curl_multi_fdset(cm, &fd_read, &fd_write, &fd_except, &max_fd)) {
        fprintf(stderr, "E: curl_multi_fdset\n");
        return EXIT_FAILURE;
      if(!curl_multi_timeout(cm, &curl_timeo)) {
        fprintf(stderr, "E: curl_multi_timeout\n");
        return EXIT_FAILURE;
      if(curl_timeo == -1)
        curl_timeo = 100;
	  //如果max_fd返回-1,休眠一段时间后继续执行curl_multi_perform
      if(max_fd == -1) {
        sleep((unsigned int)curl_timeo / 1000);
      else {
        T.tv_sec = curl_timeo/1000;
        T.tv_usec = (curl_timeo%1000)*1000;
		/* 执行监听,当文件描述符状态发生改变的时候返回
         * 返回0,程序调用curl_multi_perform通知curl执行相应操作
         * 返回-1,表示select错误
        if(0 > select(max_fd+1, &fd_read, &fd_write, &fd_except, &T)) {
          fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n",
              max_fd+1, curl_timeo, errno, strerror(errno));
          return EXIT_FAILURE;
    while((msg = curl_multi_info_read(cm, &msgs_left))) {
      if(msg->msg == CURLMSG_DONE) {
        char *url;
        CURL *e = msg->easy_handle;
        curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);
        fprintf(stderr, "R: %d - %s <%s>\n",
                msg->data.result, curl_easy_strerror(msg->data.result), url);
		/*当一个easy handler传输完成,此easy handler仍然仍然停留在multi stack中,
		调用curl_multi_remove_handle将其从multi stack中移除,然后调用curl_easy_cleanup将其关闭*/
        curl_multi_remove_handle(cm, e);
        curl_easy_cleanup(e);
      else {
        fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
  }while(still_running);
  //当multi stack中的所有传输都完成时,调用 curl_multi_cleanup关闭multi handler
  curl_multi_cleanup(cm);
  curl_global_cleanup();
  return EXIT_SUCCESS;
                    libcurl主要提供了两种发送http请求的方式,分别是Easy interface方式和multi interface方式,前者是采用阻塞的方式发送单条数据,后者采用组合的方式可以一次性发送多条数据一、Easy interfacelibcurl的easy interface是最基本的用法,首先调用curl_easy_init获取一个句柄,curl_easy_setopt函数用来设置
function _curl_post3($url,$arrs,$flen){
	for($i=0;$i&lt;$flen;$i++){
		foreach($arrs[$i] as $k=&gt;$v) $tmp_str.=$k."=".$v."&amp;";
		${'ch'.$i} = curl_init();
		curl_setopt(${'ch'.$i}, CURLOPT_URL, ...
				
目前为目最全的CURL中文说明了,学PHP的要好好掌握.有很多的参数.大部份都很有用.真正掌握了它和正则,一定就是个采集高手了. PHP中的CURL函数(Client URL Library Function) curl_close — 关闭一个curl会话 curl_copy_handle — 拷贝一个curl连接资源的所有内容和参数 curl_errno — 返回一个包含当前...
php中curl_init()的作用很大,尤其是在抓取网页内容或文件信息的时候,例如之前文章curl获得header检测GZip压缩的源代码就介绍到curl_init()的强大。 curl_init()处理事物是单线程模式,如果需要对事务处理走多线程模式,那么php里提供
size_t getUrlResponse(void *buffer, size_t size, size_t count, void *response) string *str = (string*)response; (*str).append((char*)buffer, size*count); return size * count; //post请求 string upload(string url, string data) string r.
curl命令是一个功能强大的网络工具,它能够通过http、ftp等方式下载文件,也能够上传文件。其实curl远不止前面所说的那些功能,大家可以通过man curl阅读手册页获取更多的信息。类似的工具还有wget。 curl命令使用了libcurl来实现,libcurl常用在C程序中用来处理HTTP请求curlpp是libcurl的一个C++封装,这几个东西可以用在抓取网页、网络...
libcurl是一个C语言,用于支持各种协议的数据传输。在编写代码时,需要先下载libcurl的开发,然后在代码中包含相应的头文件。接着,需要链接libcurl文件。 以下是在Linux操作系统下使用gcc编译调用libcurl的示例: 1. 安装libcurl开发 可以使用包管理器安装libcurl开发,例如在Ubuntu/Debian系统下执行以下命令: sudo apt-get install libcurl4-gnutls-dev 2. 编写代码 在代码中,需要包含curl/curl.h头文件,并调用libcurl提供的函数进行数据传输。例如: #include <curl/curl.h> int main(void) CURL *curl; CURLcode res; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com"); res = curl_easy_perform(curl); if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); return 0; 3. 编译代码 在命令行中执行以下命令进行编译: gcc -o myprogram mycode.c -lcurl 其中,myprogram为可执行文件名,mycode.c为代码文件名。参数-lcurl指定链接libcurl。 4. 运行程序 在命令行中执行以下命令运行程序: ./myprogram 以上就是使用gcc编译调用libcurl基本步骤。在编程过程中,还需要注意设置相关选项以满足自己的需求。