osx下libcurl的使用
来源:互联网 发布:手机数据恢复多少钱 编辑:程序博客网 时间:2024/06/07 02:20
osx下已经预安装了curl,关于curl的使用方法可自行百度。本文主要说的是安装及使用libcurl库进行网页捕获程序的编写。
一、安装
1. 到官网(http://curl.haxx.se/download.html)下载最新版本的源码
2. 解压,在终端进入文件夹
3. 配置选项,编译安装
# ./configure --prefix=/usr/local/curl
# make
# sudo make install
执行完上面的指令后,在目录/usr/local/curl下会bin include lib share这几个目录。包含了编译生产的库、头文件等。
二、使用libcurl库
使用流程:
· 调用curl_global_init()初始化libcurl
· 调用 curl_easy_init()函数得到 easy interface型指针
· 调用curl_easy_setopt设置传输选项
· 根据curl_easy_setopt设置的传输选项,实现回调函数以完成用户特定任务
· 调用curl_easy_perform()函数完成传输任务
· 调用curl_easy_cleanup()释放内存
在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。
1. 初始化 curl_global_init(long flag);
使用libcurl之前应该对其全局进行初始化。该函数接受一个参数,以确定如何初始化。
常用参数是:CURL_GLOBAL_ALL。会使libcurl初始化所有的子模块和一些默认的选项
可选参数是:CURL_GLOBAL_WIN32。只应用于Windows平台。它告诉libcurl初始化winsock库。如果winsock库没有正确地初始化,应用程序就不能使用socket。
CURL_GLOBAL_SSL。如果libcurl在编译时被设定支持SSL,那么该参数用于初始化相应的SSL库。
CURL_GLOBAL_NOTHING //没有额外的初始化。
libcurl有默认的保护机制,如果在调用curl_easy_perform时它检测到还没有通过curl_global_init进行初始 化,libcurl会根据当前的运行时环境,自动调用全局初始化函数。但必须清楚的是,让系统自已初始化不是一个好的选择。
当应用程序不再使用libcurl的时候,应该调用curl_global_cleanup来释放相关的资源。
***在程序中,应当避免多次调用curl_global_init和curl_global_cleanup。它们只能被调用一次。
2. 初始化一个curl的指针:curl_easy_init()
在条用结束时要用curl_easy_cleanup函数清理。
一般curl_easy_init()意味着一个会话的开始,当调用该函数时会有一个返回值,如果调用fopen()时一样。该返回值一般都用在easy系列的函数中。
3. 设置初始化后的curl句柄属性和操作:curl_easy_setopt(easy_handle, 属性类型,属性值)
在easy handle中设置了相应的属性和操作后,它们将一直作用该easy handle。也就是说,重复使用easy hanle向远程主机发出请求,先前设置的属性仍然生效。
①. curl_easy_setopt(easy_handle, CURLOPT_URL, “http://www.baidu.com“);
为句柄easy_handle设置URL
②. curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
为句柄easy_handle设置回调函数,即当有数据来的时候,执行回调函数。
回调函数的原型是:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
@param [in] buffer 当有数据到达的时候把数据缓存在buffer里
@param [in] size 每一个数据块的大小
@param [in] nmemb 数据块的数量
@param [in/out] userp 用户的指针,该指针可以在CURLOPT_WRITEDATA中指定
③. curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &internal_struct);
指定用户的打开文件,使之可以输出到文件中
④. curl_easy_perform(easy_handle);
执行简单句柄
下面是一个简单的示例程序:
#include <stdio.h>#include <curl/curl.h>#include <cstring>#include <iostream>using namespace std;/***@brief libcurl接收到数据时的回调函数*@param [in] buffer 接收到的数据所在的缓冲区*@param [in] size 数据长度*@param [in] nmemb 数据片数量*@param [in/out] 用户自定义指针*@return 获取的数据长度*/size_t process_data(void *buffer, size_t size, size_t nmemb, void *user_p){FILE *fp = (FILE *)user_p;size_t return_size = fwrite(buffer, size, nmemb, fp);cout << (char *)buffer << endl;return return_size;}int main(){CURL *easy_handle = curl_easy_init();char url[] = "http://www.baidu.com";if (NULL == easy_handle){cerr << "get a easy handle failed." << endl;return -1;}FILE *fp = fopen("data.html", "ab+");curl_easy_setopt(easy_handle, CURLOPT_URL, url);curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, &process_data);curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fp);curl_easy_perform(easy_handle);fclose(fp);curl_easy_cleanup(easy_handle);return 0;}
编译的时候记得带上 -lcurl
还有一些其他属性可以通过curl_easy_setopt设置
CURLOPT_VERBOSE属性设置为1,libcurl会输出通信过程中的一些细节。如果使用的是http协议,请求头/响应头也会被输出。
CURLOPT_HEADER设为1,这些头信息将出现在消息的内容中。
3. 关闭创建的easy_handle:curl_easy_cleanup(easy_handle)
4. 上传数据
libcurl提供协议无关的方式进行数据传输。所以上传一个文件到FTP服务器,跟向HTTP服务器提交一个PUT请求的操作方式是类似的:
①. 创建easy handle或者重用先前创建的easy handle。
②. 设置CURLOPT_URL属性。
③. 编写回调函数。
在执行上传的时候,libcurl通过回调函数读取要上传的数据。(如果要从远程服务器下载数据,可以通过回调来保存接收到的数据。)回调函数的原型如下:
bufptr指针表示缓冲区,用于保存要上传的数据,size表示每一个数据块的大小,nitems表示数据块的数量,因此size * nitems是缓冲区数据的长度,userp是一个用户自定义指针,libcurl不对该指针作任何操作,它只是简单的传递该指针。可以使用该指针在应用程序与libcurl之间传递信息。
④. 注册回调函数,设置自定义指针。语法如下:
⑤. 告诉libcurl,执行的是上传操作。
有些协议在没有预先知道上传文件大小的情况下,可能无法正确判断上传是否结束,所以最好预先使CURLOPT_INFILESIZE_LARGE属性:告诉它要上传文件的大小:
⑥. 调用curl_easy_perform。
接下来,libcurl将会完成剩下的所有工作。在上传文件过程中,libcurl会不断调用先前设置的回调函数,用于将要上传的数据读入到缓冲区,并执行上传。
5. 使用libcurl以post方式向HTTP服务器提交数据
在网站上找到form标签中的name属性
然后把值上传上去
#include <stdio.h>#include <cstring>#include <algorithm>#include <iostream>#include <curl/curl.h>using namespace std;int main(){char url[] = "http://paste.ubuntu.com";CURLcode code = curl_global_init(CURL_GLOBAL_ALL);CURL *easy_handle = curl_easy_init();curl_easy_setopt(easy_handle, CURLOPT_URL, url); curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, "poster=123&syntax=text&content=123");//curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, "username=zz&password=zz");code = curl_easy_perform(easy_handle);curl_easy_cleanup(easy_handle);curl_global_cleanup();return 0;}
*在C++中使用libcurl时,回调函数不能是类的非静态成员函数。例如:
6. 服务器与客户端之间的cookie认证
在应用场景中,你可能需要保存服务器发送给你的cookie,并在接下来的请求中,把这些cookie一并发往服务器。所以,可以把上次从服务器收到的所有响应头信息保存到文本文件中,当下次需要向服务器发送请求时,通过CURLOPT_COOKIEFILE属性告诉libcurl从该文件中读取 cookie信息。
如果你需要使用NetScape或者FireFox浏览器的cookie文件,你只要用这些浏览器的cookie文件的路径来初始化 CURLOPT_COOKIEFILE属性,libcurl会自动分析cookie文件,并在接下来的请求过程中使用这些cookie信息。
libcurl甚至能够把接收到的cookie信息保存成能被Netscape/Mozilla的浏览器所识别的cookie文件。通过把这些称为 cookie-jar。通过设置CURLOPT_COOKIEJAR选项,在调用curl_easy_cleanup释放easy handle的时候,所有的这些cookie信息都会保存到cookie-jar文件中。这就使得cookie信息能在不同的easy handle甚至在浏览器之间实现共享。
*cookie设置的文本文件路径地址,在登陆完之后无法查看到cookie文件,由此可知cookie是存放在内存中了。
#include <stdio.h>#include <cstring>#include <algorithm>#include <curl/curl.h>#include <iostream>using namespace std;CURL *easy_handle;CURLcode code;FILE *curl_file;void prepareCurl(){code = curl_global_init(CURL_GLOBAL_ALL);if (code != CURLE_OK){cerr << "init libcurl failed." << endl;}easy_handle = curl_easy_init();if (NULL == easy_handle){cerr << "get a easy handle failed." << endl;curl_global_cleanup();}//curl_easy_setopt(easy_handle, CURLOPT_TIMEOUT, 90);//curl_easy_setopt(easy_handle, CURLOPT_CONNECTTIMEOUT, 90); curl_easy_setopt(easy_handle, CURLOPT_COOKIEFILE, "cookies/");curl_easy_setopt(easy_handle, CURLOPT_COOKIEJAR, "cookies/");curl_file = fopen("tmpfiles/data.html", "w");curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, curl_file);curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, NULL);}void performCurl(){fclose(curl_file);curl_easy_cleanup(easy_handle);curl_global_cleanup();}int main(){string lgin_url = "http://acm.hrbust.edu.cn/index.php?m=User&a=login";string sub_url = "http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=postCode";prepareCurl();curl_easy_setopt(easy_handle, CURLOPT_URL, lgin_url.c_str());string post = (string)"m=User&a=login&user_name=username&password=password&ajax=1";curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, post.c_str()); code = curl_easy_perform(easy_handle);if (code != CURLE_OK) cout << "login failed." << endl;string submit = (string)"jumpUrl=&language=2&problem_id=1000&source_code=#include <iostream> using name space std; int main() { int a, b; while (cin >> a >> b) {cout << a + b << en dl;}return 0;"; curl_easy_setopt(easy_handle, CURLOPT_URL, sub_url.c_str());curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, submit.c_str());code = curl_easy_perform(easy_handle);if (code != CURLE_OK) cout << "submit failed." << endl;performCurl();return 0;}
该样例是在学校oj中做的实验,完成了登录,提交代码这两项动作。
**注意:fopen("tmpfiles/data.html", "w"); 的路径必须是已经存在的,否则编译时会出现段错误。
- osx下libcurl的使用
- windows下libcurl的使用
- winXP下eclipse中libcurl的使用
- windows下使用libcurl的整理
- linux 下 libcurl 库的使用
- windows下使用libcurl
- linux下使用libcurl
- libcurl的使用(windows下和linux下)
- osx下的parallel
- libcurl的使用
- libcurl的使用
- libcurl的使用总结
- libcurl的使用
- libcurl的使用总结
- libcurl的简单使用
- libcurl的简单使用
- libcurl的使用
- libcurl库的使用
- 大数阶乘
- XManager Enterprise 简介
- HashMap的工作原理
- FZU 1920 Left Mouse Button(dfs)
- js中push()的用法
- osx下libcurl的使用
- 百度地图、Google地图的缩放比例
- OMAPL138 eCAP capture
- 学习MongoDB网站汇总
- 对于事件没有反应,Jquery中的live()函数
- unix 常用命令
- C语言及程序设计初步例程-38 用break和continue改变流程
- 使用 adt-eclipse 打包 Cordova (3.0及其以上版本) + sencha touch 项目
- 阿里云centos 6.5 java tomcat安装 [转]