背景
 
  结合上一篇CLion之C++框架篇-优化框架,引入boost(三),继续进行框架优化!在项目中,我们经常会通过get方式拉取第三方资源,这一版优化引入类库curl,用来拉取第三方资源库。
 
  开源框架代码:https://github.com/rtxbc/cplus/tree/master/work
 
配置使用
 
  

cmake_minimum_required(VERSION 3.11.2)

project(work)

message(STATUS "start load boost ========================================")
# BOOST
## 设置个变量控制
SET(BOOST_MIN_VERSION "1.67.0")
## 动态查找
FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error:Boost (version >=${BOOST_MIN_VERSION}) required.\n")
endif()
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES: ${BOOST_LIBRARY_DIRS}")
message(STATUS "Boost_VERSION: ${Boost_VERSION}")
## 头文件
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
# .BOOST
message(STATUS "end load boost ========================================") # 编译google test,会在当前目录生成libtest.a静态库
add_subdirectory(lib/ext/googletest) #头文件
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/include ${PROJECT_SOURCE_DIR}lib/ext/googletest/include) #库文件 : libtest.a 添加到链接路径中
link_directories(${PROJECT_SOURCE_DIR}/lib ${PROJECT_SOURCE_DIR}/lib/ext/googletest /usr/local/opt/curl/lib/) #编译器相关设置
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/output/bin")
set(LIBRARIES pthread)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_COMPILER "clang++" ) # 显示指定使用的C++编译器
set(CMAKE_CXX_FLAGS "-g") # 调试信息
set(CMAKE_CXX_FLAGS "-Wall") # 开启所有警告
set(CMAKE_CXX_FLAGS "-lboost_date_time-mt-d") # boost #源码目录
FILE(GLOB_RECURSE SOURCEFILES ${PROJECT_SOURCE_DIR}/src/utility/*.cpp)
FILE(GLOB_RECURSE TEST_SOURCEFILES ${PROJECT_SOURCE_DIR}/src/test/*.cpp) add_custom_target(cmake-build-debug)
add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/src/main/main.cpp ${SOURCEFILES})
add_executable(work_test ${TEST_SOURCEFILES} ${SOURCEFILES}) target_link_libraries(${PROJECT_NAME} gtest ${Boost_LIBRARIES} curl)
target_link_libraries(work_test gtest ${Boost_LIBRARIES} curl)

  

使用
 
设定头部文件:
 

//
// Created by Zhou,Baochuan on 18/6/5.
// #ifndef WORK_HTTP_H
#define WORK_HTTP_H #include "common.h"
#include <curl/curl.h> namespace work {
class Http {
public:
Http();
~Http();
static string get(string url, unsigned retries = 3);
};
} #endif //WORK_HTTP_H

  

注意:get方法中增加了retries重试机制。在实现中看一下细节!

//
// Created by Zhou,Baochuan on 18/6/5.
// #include "http.h" using namespace work; Http::Http()
{
curl_global_init(CURL_GLOBAL_NOTHING);
} Http::~Http()
{
curl_global_cleanup();
} size_t req_reply(void* ptr, size_t size, size_t nmemb, void* stream) {
//cout << "----->reply" << endl;
std::string* str = (std::string*)stream;
//cout << *str << endl;
(*str).append((char*)ptr, size * nmemb);
return size * nmemb;
}
string Http::get(string url, unsigned int retries)
{
string response;
CURL *curl;
struct curl_slist *headers = NULL;
//headers = curl_slist_append(headers, "Accept: Agent-007"); curl = curl_easy_init() ;
if (curl) {
//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) &response);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0); // 传输超时
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 0); // 连接超时
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
CURLcode res = curl_easy_perform(curl); // 执行 // 重试
while (res != CURLE_OK && --retries > 0) {
res = curl_easy_perform(curl); // 执行
} curl_easy_cleanup(curl);
}
curl_slist_free_all(headers);
return response;
}

  

测试代码:

#include "common.h"
#include "http.h"
#include <gtest/gtest.h> using namespace work; // curl版本要求
TEST(curl, all)
{
EXPECT_EQ(3, CURLVERSION_NOW);
Http http;
string url = "http://47.95.220.249/";
ASSERT_FALSE(http.get(url).empty());
}

  

CURL 注意事项
 

1、解决线程安全及避免core错误问题方式

  1) curl_global_init()在多线程环境下,是线程不安全的。所以在多线程环境下,要在主线程中调用这个方法。配套的,在主线程中调用curl_global_cleanup()方法。

  2)curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); 控制域名解析的超时,其需要一个sigjmp_buf型的全局变量,多线程时会修改它。

  3)  curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);默认情况下libcurl完成一个任务以后,出于重用连接的考虑不会马上关闭。如果没有新的TCP请求来重用这个连接,那么只能等到CLOSE_WAIT超时,这个时间默认在7200秒甚至更高,太多的CLOSE_WAIT连接会导致性能问题

2、要想让curl_easy_perform(),能够执行,必须得有个配套方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);

 
 
推荐

CLion之C++框架篇-优化开源框架,引入curl,实现get方式获取资源(四)的更多相关文章

  1. CLion之C++框架篇-优化框架,引入boost(三)

      背景   结合上一篇CLion之C++框架篇-优化框架,单元测试(二),继续进行框架优化!这一版优化引入一个我们日常经常使用的操作库Boost,估算使用频率在70%以上!   Boost的优势在哪 ...

  2. [转]Android中Xposed框架篇—利用Xposed框架实现拦截系统方法

    一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xpo ...

  3. CLion之C++框架篇-优化框架,单元测试(二)

    背景   结合上一篇CLion之C++框架篇-安装工具,基础框架的搭建(一),继续进行框架优化!   googletest(GTest)是Google开源的C++测试框架,与CLion组合,对C++环 ...

  4. 转载一篇c++开源框架和库

    值得学习的C语言开源项目 -1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性 ...

  5. [转载] Android中Xposed框架篇---利用Xposed框架实现拦截系统方法

    本文转载自: http://www.wjdiankong.cn/android%E4%B8%ADxposed%E6%A1%86%E6%9E%B6%E7%AF%87-%E5%88%A9%E7%94%A8 ...

  6. 开源框架.netCore DncZeus学习(五)下拉树的实现

    千里之行,始于足下,先从一个小功能研究起,在菜单管理页面有一个下拉树,先研究下它怎么实现的 1.先找到menu.vue页面 惯性思维先搜索请选择三个字,原来是动态生成的 再向上找DropDown组件, ...

  7. 开源框架.netCore DncZeus学习(四)项目升级

    今天发现开源代码从1.0.0.1升级到了1.0.1.0,主要去掉了id主键,升级办法打开DncZeus,右键Git Bash Here,输入以下命令 合并失败,因为上一节尝试修改了几个代码,解决办法 ...

  8. 开源框架.netCore DncZeus学习(三)增加一个菜单

    框架运行起来了,先尝试增加一个菜单. 本节增加一个菜单名字:公司管理,需要注意一点,所有的name都要保持一致,注意圈中部分.为了防止手敲代码出错,建议复制已有的代代码进行修改(比如这里用的Role页 ...

  9. 开源框架.netCore DncZeus学习(二)配置连接

    配置连接字符串,update-database,初始数据后,访问报错,提示offset错误.因为本机上使用的sql2008. .net Core 2.X中的EF访问sqlserver2008默认使用的 ...

随机推荐

  1. 【Spring学习】Spring的源码解析之路 ——【step1】基础环境配置 + IDEA快捷键整理

    前导: 本次主要是关于“基础环境搭建”的内容,分为三个部分,(1)查看源码和项目需要的开发集成环境Intellig IDEA的使用,(2)如何导入源码,(3)在这个过程中梳理出的快捷键 正文:==== ...

  2. jQuery index() 方法

    比如同一级有多个li,获得点击的元素的下标,确定第几个. $("li").click(function(){alert($(this).index());});

  3. Junit集成测试

    Spring4.x高级话题(七):Spring的测试 一. 点睛 测试是开发工作中不可缺少的部分,单元测试只针对当前开发的类和方法进行测试,可以简单通过模拟依赖来实现,对运行环境没有依赖:但是仅仅单元 ...

  4. 【Rails App】 应用服务器从Passenger切换为Puma, Grape出现线程安全问题

    Grape中的代码如下: def market @market ||= Market.find(params[:id]) end @market基于类层次的实例变量,属于非线程安全,如果一直使用多线程 ...

  5. Unity3D UI适配

    直接贴图

  6. Javaweb拦截器

    http://blog.csdn.net/reggergdsg/article/details/52962774

  7. nsq 初试

    nsqlookupd tcp 4160 http 4161nsqd 4150nsqadmin 4171 1:安装$ brew install nsq1) 停止nsq默认的启动$ brew servic ...

  8. LinkedList - 好一个双向链表

    LinkedList是常用的集合结构之一,数据存储结构为链式存储,每个节点都有元素.前指针和后指针,指针指向了前节点和后节点的位置.同是LinkedList也是一个队列,实现了Deque接口,Dequ ...

  9. EL和JSTL笔记

    1.EL表达式 [1] 简介 > JSP表达式 <%= %> 用于向页面中输出一个对象. > 到JSP2.0时,在我们的页面中不允许出现 JSP表达式和 脚本片段. > ...

  10. android 开发案列汇总

    Android 开发案列汇总 1.一款轻量级的便签软件,界面简单干净,绿色无广告.支持部分Markdown语法,可以方便地输入和预览Markdown文本,并且生成长微博图片保存到本地. 文章来源:ht ...