在项目中使用到了libcurl,gui图形界面通过url向主进程获取、传递参数,通过查看代码,发现通过curl可以做到如此强大的功能,很强大。
在网上查资料。php使用curl是最多的,通过curl获取http url请求/web站点各阶段相应时间,因为我们的环境限制,只能采用c语言,所以我也只能通过c语言来验证。
首先还是对curl做一个简单的介绍吧,cURL是一个利用URL语法在命令行下工作的文件传输工具,它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。
curl 是一个linux工具,通过命令行来实现其强大的功能。但通过libcurl,可以在各种开发环境中通过编码的 形式实现curl上传、下载功能,其中涉及GET、PUT、POST、DELETE等方法。cURL支持的通信协议有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。可谓是支持力度相当大的一个工具了。
我们的项目中已经搭建好了服务器,网址和对应的url已经实现,我只是通过以下的代码向服务器获取信息而已。
在基于LibCurl的程序里,主要采用callback function (回调函数)的形式完成传输任务,用户在启动传输前设置好各类参数和回调函数,当满足条件时libcurl将调用用户的回调函数实现特定功能。下面是利用libcurl完成传输任务的流程:
1 调用curl_global_init()初始化libcurl
2. 调用curl_easy_init()函数得到 easy interface型指针
3. 调用curl_easy_setopt()设置传输选项
4. 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务
5. 调用curl_easy_perform()函数完成传输任务
6. 调用curl_easy_cleanup()释放内存
在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。
代码如下:
#include "stdio.h"
#include "unistd.h"
#include "sys/time.h"
#include "time.h"
#include "curl.h"
/* 回调函数, 一定要遵循会点函数的格式 */
static size_t httpCurlResCallback(void* buffer, size_t size, size_t nmemb, void* pUserArg)
{
size_t len = 0;
printf("%s; buffer = %s\n", __FILE__, buffer);
len = size * nmemb;
return len;
}
int main(int argc, const char *argv[])
{
CURLcode curlRet = 0;
CURL* pHandle = NULL;
long *pHttpCode;
char pRes[2048]= {0};
char url[128] = "http://127.0.0.1:6010/matain/dev/time";
/* 全局初始化 */
curlRet = curl_global_init(CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32);
if(curlRet != 0)
{
printf("curl_global_init() error. curlRet = %d\n", curlRet);
goto EXIT;
}
/* 初始化libcurl会话 */
pHandle = curl_easy_init();
if(NULL == pHandle)
{
printf("curl_easy_init()error.\n");
goto EXIT;
}
/* 设置连接超时时间 2秒*/
curlRet = curl_easy_setopt(pHandle, CURLOPT_CONNECTTIMEOUT, 2);
if(curlRet != 0)
{
printf("curl_easy_setopt() error! curlRet = %d\n", curlRet);
goto EXIT;
}
/* 设置超时时间 5秒*/
curlRet = curl_easy_setopt(pHandle, CURLOPT_TIMEOUT, 5);
if(curlRet != 0)
{
printf("curl_easy_setopt() error! curlRet = %d\n", curlRet);
goto EXIT;
}
/* 设置url*/
curlRet = curl_easy_setopt(pHandle, CURLOPT_URL, url);
if(curlRet != 0)
{
printf("curl_easy_setopt() error. curlRet = %d\n", curlRet);
goto EXIT;
}
/* 设置 获取方法 GET*/
curlRet = curl_easy_setopt(pHandle, CURLOPT_HTTPGET, 1L);
if(curlRet != 0)
{
printf("curl_easy_setopt() error. curlRet = %d\n", curlRet);
goto EXIT;
}
/* 设置 回调函数 */
curlRet = curl_easy_setopt(pHandle, CURLOPT_WRITEFUNCTION, httpCurlResCallback);
if(curlRet != 0)
{
printf("curl_easy_setopt() error. curlRet = %d\n", curlRet);
goto EXIT;
}
/*传入回调函数需要的结构体的指针 */
curlRet = curl_easy_setopt(pHandle, CURLOPT_WRITEDATA, (void *)pRes);
if(curlRet != 0)
{
printf("curl_easy_setopt() error. curlRet = %d\n", curlRet);
goto EXIT;
}
/* 执行curl */
curlRet = curl_easy_perform(pHandle);
if(curlRet != 0)
{
printf("curl_easy_perform() error. curlRet = %d\n", curlRet);
goto EXIT;
}
curlRet = curl_easy_getinfo(pHandle, CURLINFO_RESPONSE_CODE, pHttpCode);
if(curlRet != 0)
{
printf("curl_easy_getinfo() error. curlRet = %d\n", curlRet);
goto EXIT;
}
printf("pHttpCode = %ld\n", pHttpCode);
//释放curl对象
curl_easy_cleanup(pHandle);
//释放全局curl对象
curl_global_cleanup();
EXIT:
return 0;
}
此代码中涉及到几个重要的函数,下面详细说一下:
CURLcode curl_global_init(long flags);
在主线程中调用这个函数。(若该函数在curl_easy_init函数调用前未调用,libcurl库会自动调用优先调用,故最好显式调用一次,避免线程中被libcurl重复调用)
参数:flags
CURL_GLOBAL_ALL //初始化所有的可能的调用。
CURL_GLOBAL_SSL //初始化支持 安全套接字层。
CURL_GLOBAL_WIN32 //初始化win32套接字库。
CURL_GLOBAL_NOTHING //没有额外的初始化
CURL curl_easy_init( );
初始化一个libcurl会话, 它会返回一个用在easy系列的函数中的easy_handle(CURL对象)
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
该函数时curl使用中最重要的函数,几乎所有的curl 程序都要频繁的使用它.其功能时设置curl参数。其参数如下:
handle: CURL类型的指针
option:各种参数选项(CURLOPT_CONNECTTIMEOUT、CURLOPT_TIMEOUT等)
parameter: 既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.
CURLcode curl_easy_perform(CURL *handle);
根据设置的选项,运行curl。
curl_easy_getinfo
从curl句柄里获取附加信息。
void curl_easy_cleanup(CURL *handle);
结束会话.与curl_easy_init配套使用,成对出现.
void curl_global_cleanup(void);
清理libcurl,与curl_global_init配套使用,成对出现.
有关libcurl中最重要的函数curl_easy_setopt(),简单介绍一下其常用的参数选项:
编译: 因为用到了libcurl库和libpthread库,所以编译时时需要指定该库名字
gcc test.c -o test -lcurl -lpthread
执行: ./test
其中服务气端时已经写好的jason格式的响应。获取到的内容即为{“time”: “2030-06-03 16:04:52”},客户端可根据实际应用解析jason数据。
通过这个小程序,简单实现了利用libcurl向服务器下载数据的客户端程序。