libcurl curl_easy_perform 报告“无法解析主机名”(代码 6)

问题描述 投票:0回答:1

每次运行下面的代码时,我都会立即确定地收到此错误。

我正在尝试使用我使用 nmap 从源代码构建的 libcurl 并使用推荐的过程,有趣的是,我能够使用构建的curl 二进制文件成功发送相同的 GET 请求。我也可以使用 Postman 成功发送此查询。

这是我正在使用的curl命令(我使用

<my.website>
代替实际主机,使用
<token>
代替实际正确的令牌):

PS> cd C:\curl-8.8.0\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\bin
PS> ./curl --header "Authorization: Bearer <token>" https://<my.website>/api/test

...我得到了预期的结果:

Hello back

但是,当我在 Visual Studio 2022 中的 C++ x86 项目中尝试相同的操作时,如下所示:

#include <curl/curl.h>
#include <iostream>

void test(CURL* curl) {

    // setup
    const char* url = "https://<my.website>/api/test";
    curl_easy_setopt(curl, CURLOPT_URL, url);
    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Authorization: Bearer <token>");
    setres = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);

    // request
    CURLcode res;
    res = curl_easy_perform(curl);
    std::cerr << "RESULT: " << res << std::endl;

    // request result checking
    if (res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
    } else {
        std::cout << "POST request sent successfully!" << std::endl;
    }

    // cleanup
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
}


int main() {

    // global initialization
    CURL * curl;
    curl_global_init(CURL_GLOBAL_SSL);

    curl = curl_easy_init();
    if (curl) {
        test(curl);
    } else {
        std::cerr << "INIT FAILED" << std::endl;
    }

    // global cleanup
    curl_global_cleanup();
}

...我得到以下输出:

* getaddrinfo() thread failed to start
* Could not resolve host: <my.website>
* Closing connection
RESULT: 6
curl_easy_perform() failed: Couldn't resolve host name

又只是一个占位符;当然,真正的输出包含实际的网站)

这个问题立即出现,等待时间基本为零(根据我找到的一些答案,非零等待时间可能表明 DNS 问题)。

我已经在 Windows 11 上以 x86 模式构建了 libcurl“8.8.0 Schannel WinIDN”(使用 VS 2022 的开发人员命令提示符)。这创建了

C:\curl-8.8.0\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\
以及
include
lib
bin
子目录。

我的项目构建为 x86 项目,属性中有以下选项:

C/C++ / General / Additional Include Directories: C:\curl-8.8.0\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\include
C/C++ / Preprocessor / Preprocessor Definitions: CURL_STATICLIB;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
Linker / General / Additional Library Directories: C:\curl-8.8.0\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\lib
Linker / Input / Additional Dependencies: libcurl_a.lib;Ws2_32.lib;Wldap32.lib;Crypt32.lib;Normaliz.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)

在试图找出问题所在时,我已阅读这篇文章getaddrinfo线程无法启动#6495,建议还执行以下操作:

    curl_version_info_data* ver = curl_version_info(CURLVERSION_NOW);
    std::cerr << "VERSION: " << curl_version() << std::endl;
    if (!(ver->features & CURL_VERSION_ASYNCHDNS)) {
        std::cerr << "SYNCHRONOUS" << std::endl;
    } else if (!ver->age || ver->ares_num) {
        std::cerr << "ARES" << std::endl;
    } else {
        std::cerr << "THREADED" << std::endl;
    }

...输出:

VERSION: libcurl/8.8.0 Schannel WinIDN
THREADED

这正是我所期望的。


编辑:

在煞费苦心地单步执行 libcurl 调用之后,我发现它最终在这段代码上失败了:

  listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if(listener == CURL_SOCKET_BAD)
    return -1;

我无法进入

socket
函数来调试那里发生的事情。


编辑2:

我认为

socket()
方法实际上是一个 Windows 方法,所以我创建了一个单独的项目,其中只添加了这个库:

Linker / Input / Additional Dependencies: Ws2_32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)

...那么即使只是简单的代码:

#include <iostream>
#include <winsock.h>

int main() {

    // Create a socket (IPv4, TCP)
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        std::cerr << "Failed to create socket" << std::endl;
        return 1;
    }
    std::cerr << "OK" << std::endl;

}

...结果:

Failed to create socket

有人可以告诉我我做错了什么吗?

c++ x86 visual-studio-2022 libcurl schannel
1个回答
0
投票

解决方案(也如@Botje建议的那样)是在

main()
方法开始时进行适当的初始化:

    // Initialize Winsock
    WSADATA wsaData;
    int iResult;
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

这解决了它。

© www.soinside.com 2019 - 2024. All rights reserved.