libcurl__001__学习easy接口(一)__获取URL内容

编译器: MinGW64 (GCC)

构建工具: CMake + Ninja

依赖库: libcurl

 

实现步骤:

① 全局初始化
   函数:curl_global_init(CURL_GLOBAL_ALL)

② 创建句柄
   函数:curl_easy_init()

③ 设置必要选项
   函数:curl_easy_setopt()

④ 清理资源
   说明:如果资源创建成功,创建资源和清理资源应该成对出现
   函数:curl_easy_cleanup()
 
CMakeLists.txt
 1 2 
 3 #声明CMake和C++的最低版本要求
 4 cmake_minimum_required(VERSION 3.10.0)
 5 set(CMAKE_CXX_STANDARD 11)
 6 
 7 #定义项目的基本信息
 8 project(realtime_scene_analyzer VERSION 0.1.0 LANGUAGES CXX)
 9 
10 #启用CTest测试框架
11 include(CTest)
12 enable_testing()
13 
14 #查找系统中安装的OpenCV库
15 find_package(OpenCV REQUIRED)
16 find_package(CURL REQUIRED)
17 
18 #创建一个可执行文件目标
19 add_executable(RSA test01.cpp)
20 
21 #将库链接到可执行目标
22 target_link_libraries(RSA 
23     ${OpenCV_LIBS}
24     CURL::libcurl  
25 )
26 
27 #设置CPack打包工具的项目名称
28 set(CPACK_PROJECT_NAME ${PROJECT_NAME})

 

test01.cpp

#include <iostream>
#include <string>
#include <curl/curl.h> // 引入 libcurl 头文件

// 1. 定义回调函数:这是 libcurl 的核心机制
// 当 libcurl 接收到数据时,它会调用这个函数
// 注意:在 C++ 中,这个函数必须是全局函数或者静态函数,不能是普通类成员函数
/*
 * 参数说明:
 * ptr: libcurl 传给你的数据指针(这就是下载下来的数据)
 * size: 每个数据块的大小(通常为 1)
 * nmemb: 数据块的数量
 * userdata: 你自己传进来的参数(我们在下面会传一个 string 的地址进去)
 */
static size_t WriteCallback(void *ptr, size_t size, size_t nmemb, void *userdata) {
    // 将 void* 转换回我们熟悉的 string&
    std::string &response_string = *(static_cast<std::string*>(userdata));
    
    // 计算数据总长度
    size_t total_size = size * nmemb;
    
    // 将数据拷贝到 string 中
    response_string.append(static_cast<char*>(ptr), total_size);
    
    // 必须返回处理的字节数,否则 libcurl 会认为出错并停止下载
    return total_size;
}

int main() {
    // ==================== 第一步:全局初始化 ====================
    // 这个只需要在整个程序生命周期中调用一次
    //curl_global_init负责初始化网络库
    //CURL_GLOBAL_ALL用于初始化所有能被初始化的功能
    CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
    if (res != CURLE_OK) {
        std::cerr << "libcurl 全局初始化失败: " << curl_easy_strerror(res) << std::endl;
        return 1;
    }


    // ==================== 第二步:创建 Easy Handle ====================
    //句柄:本质是一个不透明的指针或表示符,用来代表某个内部对象,开发者不需要关心内部的工作逻辑,只需要知道如何使用即可
    // 每一个传输任务都需要一个独立的 Handle
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "Easy Handle 创建失败" << std::endl;
        curl_global_cleanup();
        return 1;
    }

    // 准备一个字符串,用来接收下载回来的网页内容
    std::string response_data;

    // ==================== 第三步:设置各种选项 (Options) ====================
    //curl_easy_setopt()中第一个参数是句柄,第二参数是选项类型(声明要设置的是功能),第三个参数是可变参数,也就是同一个函数可以根据类型第二个参数的不同,接收不同类型的第三个参数(这里第三个参数是声明把功能设置成什么样)
    // 3.1 设置要访问的 URL
    curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get");

    // 3.2 设置超时时间(秒),防止程序卡死
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);

    // 3.3 设置回调函数:告诉 libcurl "收到数据后把数据交给谁处理"
    // WriteCallback 就是我们上面定义的那个函数
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);

    // 3.4 设置回调函数的第四个参数 (userdata)
    // 这里我们将 response_data 的地址传进去,这样 WriteCallback 就能把数据写进这个变量
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);

    // ==================== 第四步:执行任务 ====================
    // curl_easy_perform 是阻塞的,它会一直等到下载完成或出错才返回
    //它会执行的功能:
    // 建立网络连接(DNS解析、TCP握手、TLS握手)
    // 发送HTTP请求(GET/POST等)
    // 等待服务器响应
    // 接收数据(通过你设置的回调函数处理数据)
    // 返回结果(成功或失败)
    res = curl_easy_perform(curl);

    // 检查执行结果
    if (res == CURLE_OK) {
        // 任务成功,打印状态码和内容
        long http_code = 0;
        // 获取 HTTP 状态码
        //这里也使用了可变参数
        //用指针接收要获取的数据
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        
        std::cout << "HTTP 状态码: " << http_code << std::endl;
        std::cout << "下载内容: " << std::endl << response_data << std::endl;
    } else {
        // 任务失败,打印错误信息
        //curl_easy_strerror(res)把错误代码转化成人类可读的信息
        std::cerr << "下载失败: " << curl_easy_strerror(res) << std::endl;
    }

    // ==================== 第五步:清理资源 ====================
    // 先清理 Easy Handle
    curl_easy_cleanup(curl);
    
    // 最后清理全局资源(通常在程序退出时调用)
    curl_global_cleanup();

    return 0;
}

结果如图:

image

 

posted @ 2026-04-02 09:41  freeyang8  阅读(0)  评论(0)    收藏  举报