You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++发送HTTP请求遇NETWORK_RECEIVE_ERROR连接重置问题求助

C++ HTTP请求连接重置问题排查

我在C++环境中尝试发送HTTP请求,先后使用curl和cpr库测试,但均出现连接重置问题,返回错误信息“NETWORK_RECEIVE_ERROR”。我已通过WireShark抓包分析(抓包结果显示TCP连接建立后,对方发送RST包重置连接),目前无法确定问题根源。以下是测试代码:

使用CPR库的代码

{
    std::string url = "https://openapi.keycrm.app/v1/products/categories?limit=50";

    const int max_retries = 3;
    const int delay_seconds = 2;

    cpr::Header headers = {
        {"Content-type", "application/json"},
        {"Accept", "application/json"},
        {"Cache-Control", "no-cache"},
        {"Pragma", "no-cache"},
        {"Authorization", "Bearer " + token}
    };
    for (int i = 0; i < max_retries; i++) {
        auto categoriesResponse = cpr::Get(cpr::Url{ url }, headers);
        if (categoriesResponse.error) {
            std::cerr << "Error " << categoriesResponse.error.message << std::endl;
            if (i < max_retries - 1) {  // no need to sleep on last iteration
                std::this_thread::sleep_for(std::chrono::seconds(delay_seconds));
            }
            continue;
        }

        Json::Value value;
        Json::Reader reader;
        if (!reader.parse(categoriesResponse.text, value)) {
            std::cerr << "Failed to parse categories response: " << reader.getFormattedErrorMessages() << std::endl;
            continue;
        }
    }
}

使用CURL库的代码

#include <curl/curl.h>
#include <json/json.h>
#include <thread>
#include <chrono>

// Callback function to collect the HTTP response data
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* out)
{
    size_t totalSize = size * nmemb;
    out->append((char*)contents, totalSize);
    return totalSize;
}

void BotHandler::loadCrmData()
{
    const std::string url = "https://openapi.keycrm.app/v1/products/categories?limit=50";
    const std::string url2 = "https://openapi.keycrm.app/v1/products?limit=50";

    const int max_retries = 3;
    const int delay_seconds = 2;

    // Initialize libcurl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();

    if(curl) {
        // Set common curl options
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Content-type: application/json");
        headers = curl_slist_append(headers, "Accept: application/json");
        headers = curl_slist_append(headers, "Cache-Control: no-cache");
        headers = curl_slist_append(headers, "Pragma: no-cache");
        std::string auth = "Authorization: Bearer " + crmToken;
        headers = curl_slist_append(headers, auth.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        // Make HTTP requests and parse responses in loop
        for (int i = 0; i < max_retries; i++) {
            // Categories Request
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            std::string categoriesResponse;
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &categoriesResponse);
            CURLcode res = curl_easy_perform(curl);
            if(res != CURLE_OK) {
                std::cerr << "Error in Categories Request: " << curl_easy_strerror(res) << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(delay_seconds));
                continue;
            }
            Json::Value categoriesValue;
            Json::Reader categoriesReader;
            if (!categoriesReader.parse(categoriesResponse, categoriesValue)) {
                std::cerr << "Failed to parse categories response: " << categoriesReader.getFormattedErrorMessages() << std::endl;
                continue;
            }

            // Extract categories data from categoriesValue, populate your categories map

            // Products Request
            curl_easy_setopt(curl, CURLOPT_URL, url2.c_str());
            std::string productsResponse;
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &productsResponse);
            res = curl_easy_perform(curl);
            if(res != CURLE_OK) {
                std::cerr << "Error in Products Request: " << curl_easy_strerror(res) << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(delay_seconds));
                continue;
            }
            Json::Value productsValue;
            Json::Reader productsReader;
            if (!productsReader.parse(productsResponse, productsValue)) {
                std::cerr << "Failed to parse products response: " << productsReader.getFormattedErrorMessages() << std::endl;
                continue;
            }

            // Extract products data from productsValue, populate your products map

            // If both requests are successful, break the loop
            break;
        }

        // Clean up curl
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
}

排查方向与解决方案

  1. TLS版本/加密套件不兼容
    目标服务器可能仅支持TLS 1.2及以上版本,可强制指定TLS版本:

    • 原生curl:添加curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    • cpr库:请求中添加cpr::SslVersion{cpr::SslVersion::TLSv1_2}参数
  2. 证书验证问题
    临时关闭证书验证排查(生产环境禁用):

    • 原生curl:curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    • cpr库:添加cpr::VerifySsl{false}参数
  3. 防火墙/代理拦截
    先用浏览器直接访问目标URL确认是否可正常响应,若需代理:

    • 原生curl:curl_easy_setopt(curl, CURLOPT_PROXY, "http://your-proxy:port");
    • cpr库:添加cpr::Proxy{"http://your-proxy:port"}参数
  4. 请求头优化
    GET请求可尝试移除Content-type: application/json头(GET通常无请求体),同时确认Authorization的token有效性。

  5. 服务器端限制
    换网络环境(如手机热点)测试,或联系服务器管理员确认是否存在IP黑名单、频率限制等。

额外调试建议

开启curl详细日志查看请求细节:

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

结合WireShark抓包分析TLS握手阶段是否完成,帮助定位是TLS层还是应用层问题。

内容的提问来源于stack exchange,提问作者JACKoVI4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:05:00