C/C++中libcurl的使用-Http GET方法使用详解
2018-01-21 10:24
489 查看
Curl是一个命令行工具,用于以特定的URL语法进行数据传输。libcrul是一个用于完成此项工作的curl库。借助libcurl,使用C/C++可以完成文件的下载,HTTP get,post等很多工作。本文介绍使用libcurl的C API完成HTTP中的GET操作。
下面的代码用于使用HTTP get协议,发送请求到一个网址,当请求被正确响应后,将响应的结果页面内容写成一个文件,保存在本地磁盘。
编译,执行:
程序执行完后,会在当前目录下生成名为d
c4b4
fshealth.html的文件,该文件内容即为配置的url地址的页面。
在上述代码中,程序试图获取整个网页的结果,如果客户端是多线程的,务必将CURLOPT_NOSIGNAL置为1。结构体MemoryStruct是自定义的数据结构,用于保存CURL执行的结果,CURLOPT_WRITEDATA将该对象传递给回调函数,在回调函数WriteMemoryCallback中,将返回结果分配存储空间,并拷贝返回内存到MemoryStruct对象中。通过curl_easy_getinfo获取curl执行结果的会话信息,将判断执行成功时,客户端将MemoryStruct对象的内容写到指定文件中。
相关接口及参数说明:
该函数用于操作前的全局初始化,它是非线程安全的,它应该在所有其他libcurl函数调用之前被调用,而且只能被调用一次。如果用户没有调用该函数,那么在后续调用curl_easy_init()进行初始化时,会自动调用curl_global_init(CURL_GLOBAL_DEFAULT),以确保初始化了”global SSL stuff”,参见lib/easy.c源码。
参数:
CURL_GLOBAL_ALL 初始化除CURL_GLOBAL_ACK_EINTR外的所有系统。
CURL_GLOBAL_SSL 初始化SSL
CURL_GLOBAL_WIN32 初始化Win32 socket libraries.
CURL_GLOBAL_NOTHING 不初始化任何系统
CURL_GLOBAL_DEFAULT 等同于CURL_GLOBAL_ALL
CURL_GLOBAL_ACK_EINTR 设置了这个标签后,当curl在连接或等待数据请求时,curl将接收EINTR条件,否则,curl会一直等待。
返回值:
正常通过时返回0,非零值表示出现错误。
该函数用于进行全局的清理工作,对于使用libcurl的每一个应用,应该只被调用一次。
外部接口,用于创建,分配并返回一个初始化的CURL句柄,作为其他curl_easy函数的作用对象。
外部接口,用于配置CURL对象的选项参数。上述代码中涉及的一些参数选项:
CURLOPT_TIMEOUT:一个完整的请求的超时时长,前者时间单位为秒,后者为毫秒。如果CURLOPT_TIMEOUT和CURLOPT_TIMEOUT_MS都设置了,那么后面的设置将会覆盖前面的设置。
CURLOPT_CONNECTTIMEOUT:配置在建立请求的链接阶段的超时时长限制,关于时长的参数与上面的TIMEOUT类似。
更多其他参数详见源码”docs/libcurl/opts”
下面的代码用于使用HTTP get协议,发送请求到一个网址,当请求被正确响应后,将响应的结果页面内容写成一个文件,保存在本地磁盘。
//getDataByCurl.cpp #include <iostream> #include <string> #include <curl/curl.h> #include <curl/types.h>; #include <curl/easy.h> #include <stdlib.h> #include <string.h> using namespace std; struct MemoryStruct { char *memory; size_t size; MemoryStruct() { memory = (char *)malloc(1); size = 0; } ~MemoryStruct() { free(memory); memory = NULL; size = 0; } }; size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)data; mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); if (mem->memory) { memcpy(&(mem->memory[mem->size]), ptr, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } int main() { CURLcode res = curl_global_init(CURL_GLOBAL_ALL); if(CURLE_OK != res) { cout<<"curl init failed"<<endl; return 1; } CURL *pCurl = NULL; pCurl = curl_easy_init(); if( NULL == pCurl) { cout<<"Init CURL failed..."<<endl; return -1; } string url = "http://xx.xx.xx.xx:50070/dfshealth.html"; //待请求的页面 string filename = "dfshealth.html"; //正确响应后,请请求转写成本地文件的文件名即路径,此处表示当前目录下 curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 3L);//请求超时时长 curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 10L); //连接超时时长 curl_easy_setopt(pCurl, CURLOPT_FOLLOWLOCATION, 1L);//允许重定向 curl_easy_setopt(pCurl, CURLOPT_HEADER, 0L); //若启用,会将头文件的信息作为数据流输出 curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); //得到请求结果后的回调函数 MemoryStruct oDataChunk; //请求结果的保存格式 curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &oDataChunk); curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1L); //关闭中断信号响应 curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L); //启用时会汇报所有的信息 curl_easy_setopt(pCurl, CURLOPT_URL, url.c_str() ); //需要获取的URL地址 curl_slist *pList = NULL; pList = curl_slist_append(pList,"Accept-Encoding:gzip, deflate, sdch"); pList = curl_slist_append(pList,"Accept-Language:zh-CN,zh;q=0.8"); pList = curl_slist_append(pList,"Connection:keep-alive"); curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList); res = curl_easy_perform(pCurl); //执行请求 long res_code=0; res=curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &res_code); //正确响应后,请请求转写成本地文件的文件 if(( res == CURLE_OK ) && (res_code == 200 || res_code == 201)) { FILE* fTmpMem = (FILE*)oDataChunk.memory; if (!fTmpMem) { } FILE *fp=fopen(filename.c_str(),"wb"); if(!fp) { cout<<"open file failed"; return -1; } fwrite(fTmpMem, 1, oDataChunk.size, fp); fclose(fp); return true; } curl_slist_free_all(pList); curl_easy_cleanup(pCurl); curl_global_cleanup(); return 0; }
编译,执行:
# g++ -g getDataByCurl.cpp -o run -lcurl # ./run * About to connect() to xx.xx.xx.xx port 50070 (#0) * Trying xx.xx.xx.xx... * connected * Connected to xx.xx.xx.xx (xx.xx.xx.xx) port 50070 (#0) > GET /dfshealth.html HTTP/1.1 Host: xx.xx.xx.xx:50070 Accept: */* Accept-Encoding:gzip, deflate, sdch Accept-Language:zh-CN,zh;q=0.8 Connection:keep-alive < HTTP/1.1 200 OK < Cache-Control: no-cache < Expires: Tue, 17 Oct 2017 02:49:59 GMT < Date: Tue, 17 Oct 2017 02:49:59 GMT < Pragma: no-cache < Expires: Tue, 17 Oct 2017 02:49:59 GMT < Date: Tue, 17 Oct 2017 02:49:59 GMT < Pragma: no-cache < Content-Type: text/html; charset=utf-8 < Accept-Ranges: bytes < Content-Length: 13320 < Last-Modified: Thu, 18 Aug 2016 01:49:57 GMT < Server: Jetty(6.1.26) < * Connection #0 to host xx.xx.xx.xx left intact
程序执行完后,会在当前目录下生成名为d
c4b4
fshealth.html的文件,该文件内容即为配置的url地址的页面。
在上述代码中,程序试图获取整个网页的结果,如果客户端是多线程的,务必将CURLOPT_NOSIGNAL置为1。结构体MemoryStruct是自定义的数据结构,用于保存CURL执行的结果,CURLOPT_WRITEDATA将该对象传递给回调函数,在回调函数WriteMemoryCallback中,将返回结果分配存储空间,并拷贝返回内存到MemoryStruct对象中。通过curl_easy_getinfo获取curl执行结果的会话信息,将判断执行成功时,客户端将MemoryStruct对象的内容写到指定文件中。
相关接口及参数说明:
CURL_EXTERN CURLcode curl_global_init(long flags);
该函数用于操作前的全局初始化,它是非线程安全的,它应该在所有其他libcurl函数调用之前被调用,而且只能被调用一次。如果用户没有调用该函数,那么在后续调用curl_easy_init()进行初始化时,会自动调用curl_global_init(CURL_GLOBAL_DEFAULT),以确保初始化了”global SSL stuff”,参见lib/easy.c源码。
参数:
CURL_GLOBAL_ALL 初始化除CURL_GLOBAL_ACK_EINTR外的所有系统。
CURL_GLOBAL_SSL 初始化SSL
CURL_GLOBAL_WIN32 初始化Win32 socket libraries.
CURL_GLOBAL_NOTHING 不初始化任何系统
CURL_GLOBAL_DEFAULT 等同于CURL_GLOBAL_ALL
CURL_GLOBAL_ACK_EINTR 设置了这个标签后,当curl在连接或等待数据请求时,curl将接收EINTR条件,否则,curl会一直等待。
返回值:
正常通过时返回0,非零值表示出现错误。
CURL_EXTERN void curl_global_cleanup(void);
该函数用于进行全局的清理工作,对于使用libcurl的每一个应用,应该只被调用一次。
CURL_EXTERN CURL *curl_easy_init(void);
外部接口,用于创建,分配并返回一个初始化的CURL句柄,作为其他curl_easy函数的作用对象。
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout); CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);
外部接口,用于配置CURL对象的选项参数。上述代码中涉及的一些参数选项:
CURLOPT_TIMEOUT:一个完整的请求的超时时长,前者时间单位为秒,后者为毫秒。如果CURLOPT_TIMEOUT和CURLOPT_TIMEOUT_MS都设置了,那么后面的设置将会覆盖前面的设置。
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout); CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS, long timeout);
CURLOPT_CONNECTTIMEOUT:配置在建立请求的链接阶段的超时时长限制,关于时长的参数与上面的TIMEOUT类似。
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable); CURLOPT_FOLLOWLOCATION:使用enable参数控制是否允许URL地址的重定向,关于地址的重定向请参见其他资料。 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff); CURLOPT_HEADER:当onoff被设置为1时,即告诉libcurl在输出请求体时包含头部信息。 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback); CURLOPT_WRITEFUNCTION:传递调用完成时的回调函数,回调函数的原型为: size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata); CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer); CURLOPT_WRITEDATA:一个自定义的指针pointer,用于传递给上面的write_callback CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff); CURLOPT_NOSIGNAL:如果是多线程,请将该参数置为1。这个选项用于unix环境下的多线程应用仍然可以使用各种timeout选项,而不会引发信号中断致使程序退出。 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff); CURLOPT_VERBOSE:如果将onoff置为1,那么将使得调用过程中输出更多的关于调用操作的详细信息。 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL); CURLOPT_URL:请求的url地址 curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList); CURLOPT_HTTPHEADER:设置HTTP请求的头信息
更多其他参数详见源码”docs/libcurl/opts”
CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,const char *); 向curl_slist链表中追加参数,curl_slist_append()函数是很有用的,因为如果你什么都不写,CUrl会传输一个类似"Get /你的网页 accept:*/*"之类的简单协议,在某些验证较为严格的服务器,这样的Http链接协议字会被丢弃的。 curl_slist_append()这个API可以让你伪装成一个标准的网页浏览器的请求。关于相关的请求参数,可以通过浏览器的开发者中工具中预先查看。 CURL_EXTERN void curl_slist_free_all(struct curl_slist *); 用于释放之前curl_slist中数据 CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); 外部接口,用于执行CURL对象,是一个阻塞类型的操作 CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); 从curl执行结果中获取内部信息。该函数的第三个参数必须是一个指向long,char或者double类型的指针,当函数执行结果返回CURLE_OK时,该指针的结果将会根据实际情况被填充响应的结果。 CURL_EXTERN void curl_easy_cleanup(CURL *curl); 调用该函数来结束一个curl easy会话。关闭一个由curl_easy_init()生成的handle
相关文章推荐
- 如何使用libcurl实现HTTP的GET方法获取文件长度
- 如何使用libcurl实现HTTP的GET方法获取文件长度
- 如何使用libcurl实现HTTP的GET方法获取文件长度
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(4):异步通讯层生成的客户端代理类、使用HTTP GET进行调用
- 详解php的魔术方法__get()和__set()使用介绍
- wp7使用POST请求Asp.net网页时,HttpWebRequest的BeginGetResponse方法抛出NotSupportException异常的解决方法
- 使用HTTP GET调用Web Services方法
- jQuery的ajax()检验用户名;通过jQuery的load()/get()/post()方法实现;使用XMLHTTPRequest对象来进行AJAX的异步数据交互
- C++调用JAVA方法详解_____转载自http://public0821.iteye.com/blog/423941
- 客户端访问WebService中如何使用【使用HTTP GET访问方法】
- MFC使用HttpGet和HttpPost方法与服务器通信
- 深入Atlas系列:Web Sevices Access in Atlas示例(4) - 使用HTTP GET调用Web Services方法
- 在VC中WININET使用HTTP的POSTA和GET方法
- php 中 http_build_query函数 使用方法详解
- Ubuntu下的apt-get的使用方法详解
- HTTP请求方法及响应码详解(http get post head)
- 老外编的程序(八):在CSharp里面使用Http Get方法
- 客户端访问WebService中如何使用【使用HTTP GET访问方法】
- getContentResolver().query()方法selection参数使用详解
- 如何在VC中WININET使用HTTP的POSTA和GET方法