curl 源码分析

来源:互联网 发布:淘宝网返利链接的制作 编辑:程序博客网 时间:2024/06/05 16:22

Curl 源码分析

分析下curl 的源码,免得c忘光了。
首先 curl 依赖于libcurl, 这里只分析curl命令,libcurl 分析以后会详述。

源码获取

curl网站,下载一份curl源码。

curl 源码结构

源码结构如下
先省略

curl源码分析

先从main 函数看起,废话不多说,上源码, 加注释

int main(int argc, char *argv[]){  // 返回状态码,c语言习惯,执行成功通过返回码确定。  CURLcode result = CURLE_OK;  //全局配置,配置里面东西太多,不单列了,定义了先初始化。  struct GlobalConfig global;  memset(&global, 0, sizeof(global));  // 确保 std in out err 打开。  main_checkfds();// 信号处理函数#if defined(HAVE_SIGNAL) && defined(SIGPIPE)  (void)signal(SIGPIPE, SIG_IGN);#endif  /* Initialize memory tracking */  memory_tracking_init();  /* Initialize the curl library - do not call any libcurl functions before     this point */  result = main_init(&global);  if(!result) {    /* Start our curl operation */    result = operate(&global, argc, argv);#ifdef __SYMBIAN32__    if(global.showerror)      tool_pressanykey();#endif    /* Perform the main cleanup */    main_free(&global);  }#ifdef __NOVELL_LIBC__  if(getenv("_IN_NETWARE_BASH_") == NULL)    tool_pressanykey();#endif#ifdef __VMS  vms_special_exit(result, vms_show);#else  return (int)result;#endif}

main函数里面主要调用三个函数,main_init, operate,main_free。 init 和free 对配置进行初始化和销毁动作。

来看operate的代码, operate 原封不动接收所有控制台参数,额外加上了curl的配置参数。

CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]){  CURLcode result = CURLE_OK;  /* Setup proper locale from environment */#ifdef HAVE_SETLOCALE  setlocale(LC_ALL, "");#endif  /* Parse .curlrc if necessary */  if((argc == 1) ||     (!curlx_strequal(argv[1], "-q") &&      !curlx_strequal(argv[1], "--disable"))) {    parseconfig(NULL, config); /* ignore possible failure */    /* If we had no arguments then make sure a url was specified in .curlrc */    if((argc < 2) && (!config->first->url_list)) {      helpf(config->errors, NULL);      result = CURLE_FAILED_INIT;    }  } /* 感觉注释写的很好,貌似我完全说不上啥话。 这里简单说几句  上面的代码会对参数,做一些检查,如果不正确会打印帮助文档。  下面会处理输入参数 判断一些特性是否开启,依次是:  1 打印帮助  2 打印menu  3 版本信息  4 ssl 支持  5 初始化libcurl  */  if(!result) {    /* Parse the command line arguments */    ParameterError res = parse_args(config, argc, argv);    if(res) {      result = CURLE_OK;      /* Check if we were asked for the help */      if(res == PARAM_HELP_REQUESTED)        tool_help();      /* Check if we were asked for the manual */      else if(res == PARAM_MANUAL_REQUESTED)        hugehelp();      /* Check if we were asked for the version information */      else if(res == PARAM_VERSION_INFO_REQUESTED)        tool_version_info();      /* Check if we were asked to list the SSL engines */      else if(res == PARAM_ENGINES_REQUESTED)        tool_list_engines(config->easy);      else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL)        result = CURLE_UNSUPPORTED_PROTOCOL;      else        result = CURLE_FAILED_INIT;    }    else {#ifndef CURL_DISABLE_LIBCURL_OPTION      if(config->libcurl) {        /* Initialise the libcurl source output */        result = easysrc_init();      }#endif      /* Perform the main operations */      // 这里会循环调用operate_do 来执行当前的curl 命令,真正的执行就是libcurl       if(!result) {        size_t count = 0;        struct OperationConfig *operation = config->first;        /* Get the required aguments for each operation */        while(!result && operation) {          result = get_args(operation, count++);          operation = operation->next;        }        /* Set the current operation pointer */        config->current = config->first;        /* Perform each operation */        while(!result && config->current) {          result = operate_do(config, config->current);          config->current = config->current->next;        }// 执行完毕 会清理libcurl 分配的内存。#ifndef CURL_DISABLE_LIBCURL_OPTION        if(config->libcurl) {          /* Cleanup the libcurl source output */          easysrc_cleanup();          /* Dump the libcurl code if previously enabled */          dumpeasysrc(config);        }#endif      }      else        helpf(config->errors, "out of memory\n");    }  }  return result;

这样看 operater 还是一个封装函数,不过该函数中已经对一些curl特性进行了处理,因此还是做了一部分工作的,接下来真正的大头是operater_do 这个函数,这个函数接收参数,并执行网络操作的函数。该函数代码很长。 大约有一千八百行,分开列出来。函数中还用到了goto。

0 0
原创粉丝点击