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(); }
排查方向与解决方案
TLS版本/加密套件不兼容
目标服务器可能仅支持TLS 1.2及以上版本,可强制指定TLS版本:- 原生curl:添加
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - cpr库:请求中添加
cpr::SslVersion{cpr::SslVersion::TLSv1_2}参数
- 原生curl:添加
证书验证问题
临时关闭证书验证排查(生产环境禁用):- 原生curl:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - cpr库:添加
cpr::VerifySsl{false}参数
- 原生curl:
防火墙/代理拦截
先用浏览器直接访问目标URL确认是否可正常响应,若需代理:- 原生curl:
curl_easy_setopt(curl, CURLOPT_PROXY, "http://your-proxy:port"); - cpr库:添加
cpr::Proxy{"http://your-proxy:port"}参数
- 原生curl:
请求头优化
GET请求可尝试移除Content-type: application/json头(GET通常无请求体),同时确认Authorization的token有效性。服务器端限制
换网络环境(如手机热点)测试,或联系服务器管理员确认是否存在IP黑名单、频率限制等。
额外调试建议
开启curl详细日志查看请求细节:
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
结合WireShark抓包分析TLS握手阶段是否完成,帮助定位是TLS层还是应用层问题。
内容的提问来源于stack exchange,提问作者JACKoVI4
相关产品推荐
相关产品推荐

