自己编译的curl库

01 问题 自己编译libcurl库

默认curl是不支持ssl的,需要自己勾选,并配置对应ssl代码。
一般编译都需要支持ssl,大多选择openssl开源库。
可自行编译。编译的时候,最好勾选testing选项,来编译测试文件,这样编译研究各种测试用例。

这里写图片描述

勾选cmake中的 ENABLE_THREADED_RESOLVER 选项 。
并且注释掉代码中的

        //curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
        //curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

release版本不再崩溃。

参考:
https://blog.csdn.net/delphiwcdj/article/details/18284429
https://blog.csdn.net/u013317006/article/details/20696261
https://blog.csdn.net/xuheazx/article/details/52689327

02 解决办法

curl-get.h

#pragma once
#include <string>

bool curl_get_req(const std::string &url, std::string &sBody, std::string &sHeader);

bool curl_get_req2(const std::string &url, std::string &sHeader, std::string &sBody);

curl-get.cpp

#include <iostream>  
#include <string>  
#include "curl/curl.h"  
using namespace std;

#pragma comment(lib, "ws2_32.lib")  
#pragma comment(lib, "wldap32.lib")  
#pragma comment(lib, "libcurl.lib")  

// WIN32 NDEBUG
// https://blog.csdn.net/u013317006/article/details/20696261

// https://blog.csdn.net/xuheazx/article/details/52689327
//libcurl 不支持异步 dns 解析时,会通过 signal 的方式实现 dns 解析设置超时, 
//signal 会导致多线程程序崩溃,后台服务通常都是多线程的,
//所以应该总是设置这个选项(但是 libcurl 不支持异步 dns 解析时,超时选项将被忽略)。
//可以通过运行 curl --version 命令或调用 curl_version 函数查看 libcurl 是否支持异步 dns 解析,
//调用 curl_version_info 函数还可以获得具体的 c - ares 库版本号。
//编译 libcurl 时,通过为 configure 指定 --enable - threaded - resolver 或 --enable - ares 选项启用异步 dns 解析。

// https://blog.csdn.net/delphiwcdj/article/details/18284429

size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
{
    string *str = (string*)stream;
    cout << *str << endl;
    (*str).append((char*)ptr, size*nmemb);
    return size * nmemb;
}

// 用这个函数会的 release 版本会导致进程退出
bool curl_get_req(const std::string &url, std::string &sHeader, std::string &sBody)
{
    CURL *curl = curl_easy_init();
    CURLcode res;
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
        curl_easy_setopt(curl, CURLOPT_HEADER, 0);
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&sBody);
        sHeader = "";

        res = curl_easy_perform(curl);
    }

    curl_easy_cleanup(curl);
    return true;
}

// 这种模式debug/release都正常
bool curl_get_req2(const std::string &url, std::string &sHeader, std::string &sBody)
{
    auto curl_deleter = [](CURL *curl) {curl_easy_cleanup(curl); };
    using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
    Curl curl{ curl_easy_init(), curl_deleter };
    CURLcode res;
    if (curl)
    {
        curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
        curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl.get(), CURLOPT_NOSIGNAL, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_HEADER, 0);
        curl_easy_setopt(curl.get(), CURLOPT_CONNECTTIMEOUT, 30);
        curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, 30);
        curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl.get(), CURLOPT_LOW_SPEED_TIME, 5);
        #ifdef CURL_DOES_CONVERSIONS
                curl_easy_setopt(curl.get(), CURLOPT_TRANSFERTEXT, 1L);
        #endif
        #if LIBCURL_VERSION_NUM >= 0x072400
                curl_easy_setopt(curl.get(), CURLOPT_SSL_ENABLE_ALPN, 0L);
        #endif
        curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, (void *)&sBody);
        sHeader = "";

        res = curl_easy_perform(curl.get());
    }

    return true;
}

03 debug正常/release失败,不是这个库的问题

chromium 加载自己的dll,需要注意dll调用要符合windows api规范。
debug版本没有严格按照windows api规范,所以debug版本调用正常。
release版本则必须严格按照win api标准,尤其是内存分配。
比如:你不可以用std::string &params 作为dll的回参参数。而需要使用比如 char *params这种类型的,在dll函数外表分配内存的形式。(如果动态分配内存,必须自己严格释放)

另外,com 接口的使用也必须注意。

猜你喜欢

转载自blog.csdn.net/longji/article/details/81744189