
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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) |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // // 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重试机制。在实现中看一下细节!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | // // 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; } |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #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()); } |
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);

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步