一直想写一些关于C++的博客,却一直没抽空来写,今天趁着代码打累了,来写写年前想写的博客。
在做项目时,因为我使用的后台是用.net core写的,那么C++就需要使用http协议来同后台进行交互了。C++要如何使用http协议呢?这里我推荐使用Libcurl这个库,不得不说这个库真的很强大(
有兴趣的小伙伴可以去查阅查阅),当然也可以使用其他的,下面我们进入正题。
首先大家先到网上下载libcurl,大家自行
下载,密码:
zsrb,博主这里用的是curl-7.26.0的,将“
curl-7.26.0/include/curl”
文件夹拷贝到自己的项目中,该文件夹包含了curl需要的头文件,为了方便起见我将curl的库文件也拷贝到了项目中,并放在了刚刚的curl中,库文件的地址“curl-7.26.0/lib/Debug”和"curl-7.26.0/lib/Release"。下面我们在项目中引入curl:
//引入头文件
#include "curl\curl.h"
#include "curl\easy.h"
下面我们就来说说curl的使用。
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
curl_global_init()用以初始化curl环境,curl_easy_init用来初始化一个easy curl对象。
#ifdef _DEBUG
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#endif
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt是对easy curl对象进行相关设置,需要设置哪些参数可以自行查阅。这事可以直接使用curl_easy_perform执行curl请求,但这种情况是阻塞的,所以下面我会介绍multi执行并发请求。先来看看代码
bool CLibcurl::UserLand(const std::string number, const std::string password)
{
std::string strUrl = "http://*******/User/Login"; // 接口地址
CURL *curl;
CURLM *multi_handle;
std::stringstream getstream;
int still_running;
bool IsTrue = false;
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
struct curl_slist *headers = NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "username",
CURLFORM_COPYCONTENTS, number.c_str(),
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "password",
CURLFORM_COPYCONTENTS, password.c_str(),
CURLFORM_END);
curl = curl_easy_init();
multi_handle = curl_multi_init();
if (NULL == curl || NULL == multi_handle) {
IsTrue = false;
goto exit;
}
headers = curl_slist_append(headers, buf);
#ifdef _DEBUG
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#endif
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); // 表单
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &getstream);
curl_multi_add_handle(multi_handle, curl);
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running));
while (still_running) {
switch (Select(multi_handle)) {
case -1:
break;
case 0:
std::cout << "timeout" << std::endl;
default:
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running));
break;
}
}
//对接收到的getstream进行处理
exit:
curl_global_cleanup();
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headers);
return IsTrue;
}
下面我们来分析下这个代码,此处我写的是一个简单的提交登陆表单的程序,使用curl_formadd()来构建表单,是不是发现表单构建起来变得很简单了,突然有了写javascript的感觉。curl_formadd中的 CURLFORM_COPYNAME,是后台接收时的字段名,而CURLFORM_COPYCONTENTS则是存储字段名对应的内容,比如用户的用户名,想了解更多可点击该链接。 使用multi前我们还需要用curl_multi_init()先初始化multi,虽然说multi是并发的,但其实它的使用也是非常简单的,只需将我们上面使用curl_easy_init创建的curl传入到curl_slist_append的第二个参数中就行了,接下来我们就可以用curl_multi_perform执行multi了,此处使用的是select来对事件进行监听,并通知curl执行对应操作。
上面代码中的Select函数代码如下:
int CLibcurl::Select(CURLM *multi_handle)
{
struct timeval timeout;
int rc;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// 获取文件描述符
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
return rc;
}
最后补充下,在构建表单的时候可以将文件传入表单中
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "data",
CURLFORM_FILE, filepath.c_str(), // 文件的所在地址
CURLFORM_END);
可以用这种方法来实现小文件的简单上传,curl的用法大致就说到这里了,想深入研究的朋友可以积极查阅资料。