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

如何让C++ HTTPS下载器具备代理感知能力以适配公司代理?

让C++ HTTPS下载器支持公司代理的解决方案

你的C++代码使用URLOpenBlockingStream无法通过公司代理,核心原因是这个API默认不会自动加载系统代理配置,也不处理代理认证;而C#的WebClient通过GetSystemWebProxy自动获取系统代理,并使用DefaultCredentials处理认证。以下是两种可行的解决方案:

方案一:为URLMON配置系统代理(基于原有代码修改)

URLOpenBlockingStream属于URLMON库,可通过URLMkSetSessionOption手动设置系统代理信息:

#include <urlmon.h>
#include <wininet.h>
#include <sstream>
#include <iostream>
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "wininet.lib")

using namespace std;

string downloader(char *url) {
    // 获取系统全局代理设置
    INTERNET_PER_CONN_OPTION_LIST optionList = {0};
    optionList.dwSize = sizeof(optionList);
    optionList.pszConnection = NULL;
    optionList.dwOptionCount = 1;
    optionList.pOptions = new INTERNET_PER_CONN_OPTION[1];
    optionList.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER;

    DWORD dwSize = sizeof(optionList);
    if (!InternetQueryOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &optionList, &dwSize)) {
        delete[] optionList.pOptions;
        return "";
    }

    // 将系统代理设置到URLMON会话
    HRESULT hr = URLMkSetSessionOption(URLMON_OPTION_PROXY, optionList.pOptions[0].Value.pszValue, 
                                       lstrlen(optionList.pOptions[0].Value.pszValue), 0);
    delete[] optionList.pOptions;
    if (FAILED(hr)) {
        return "";
    }

    // 自动使用当前用户凭证处理代理认证(针对NTLM类型的公司代理)
    URLMkSetSessionOption(URLMON_OPTION_PROXY_USERNAME, "", 0, 0);
    URLMkSetSessionOption(URLMON_OPTION_PROXY_PASSWORD, "", 0, 0);

    // 原有下载逻辑
    IStream *stream;
    HRESULT result = URLOpenBlockingStream(0, url, &stream, 0, 0);
    if (result != 0) {
        return "";
    }
    char buffer[100];
    unsigned long bytesRead;
    stringstream ss;
    stream->Read(buffer, 100, &bytesRead);
    while (bytesRead > 0U) {
        ss.write(buffer, (long long)bytesRead);
        stream->Read(buffer, 100, &bytesRead);
    }
    stream->Release();
    string resultString = ss.str();
    cout << resultString << endl;
    return resultString;
}

方案二:改用WinINet API(推荐,更贴近C#逻辑)

WinINet是Windows原生网络库,支持自动读取系统代理、默认凭证认证,逻辑和C#的实现完全对齐:

#include <wininet.h>
#include <sstream>
#include <iostream>
#pragma comment(lib, "wininet.lib")

using namespace std;

string downloader(char *url) {
    // 初始化网络会话,自动读取系统代理配置
    HINTERNET hInternet = InternetOpenA("C++ Proxy-Aware Downloader", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (!hInternet) {
        return "";
    }

    // 打开URL,自动处理代理连接
    HINTERNET hConnect = InternetOpenUrlA(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE, 0);
    if (!hConnect) {
        InternetCloseHandle(hInternet);
        return "";
    }

    // 读取响应内容
    char buffer[100];
    DWORD bytesRead;
    stringstream ss;
    while (InternetReadFile(hConnect, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
        ss.write(buffer, bytesRead);
    }

    // 释放资源
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    string resultString = ss.str();
    cout << resultString << endl;
    return resultString;
}

关键说明:

  • INTERNET_OPEN_TYPE_PRECONFIG参数让InternetOpen自动加载系统代理设置,对应C#的GetSystemWebProxy。
  • WinINet默认会使用当前登录用户的凭证处理代理认证,对应C#的CredentialCache.DefaultCredentials,无需额外配置即可适配公司NTLM代理。
  • WinINet比URLMON提供更灵活的代理控制,比如自定义代理地址、处理不同类型的认证等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:18:29