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

如何在boost::asio::resolver::query中传递代理服务器的用户名和密码

使用boost::asio连接带身份验证的HTTP代理服务器

你的需求是实现和curl google.com --proxy http://username:password@xx.xxx.xxx.xx:xxxx等效的C++逻辑,boost::asio完全可以实现,你之前的写法错误在于混淆了代理地址解析和代理认证逻辑的步骤,导致解析失败报「Host not found (authoritative)」。

错误原因分析

你尝试的五种写法都存在问题:

  • #1:如果xx.xxx.xxx.xx没有用字符串引号包裹,会被编译器识别为变量而非IP字符串,导致解析失败;即使加了引号,这一步只是解析代理地址,但后续未发送认证请求,代理会拒绝连接,但你的报错是地址解析失败,大概率是未加引号导致。
  • #2-#5:错误地将代理认证信息、目标URL混入resolver::query中,resolver::query仅负责解析代理服务器的IP/域名和端口,这些额外信息不属于地址解析范畴,必然导致解析失败。

正确实现步骤

要连接带身份验证的HTTP代理,需要分两步:

  1. 解析代理服务器地址并建立TCP连接;
  2. 向代理发送CONNECT请求,并在请求头中携带认证信息,请求代理建立到目标服务器的转发连接。

完整代码示例

#include <boost/asio.hpp>
#include <string>
#include <iostream>
#include <vector>

// 基础Base64编码实现(用于生成代理认证头)
std::string base64_encode(const std::string& input) {
    const std::string base64_chars = 
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";
    
    std::string result;
    int i = 0, j = 0;
    unsigned char char_array_3[3], char_array_4[4];
    
    for (unsigned char c : input) {
        char_array_3[i++] = c;
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;
            
            for (i = 0; i < 4; i++)
                result += base64_chars[char_array_4[i]];
            i = 0;
        }
    }
    
    if (i) {
        for (j = i; j < 3; j++)
            char_array_3[j] = '\0';
        
        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;
        
        for (j = 0; j < i + 1; j++)
            result += base64_chars[char_array_4[j]];
        
        while (i++ < 3)
            result += '=';
    }
    
    return result;
}

int main() {
    try {
        boost::asio::io_context io_context;
        
        // 配置代理和目标服务器信息
        const std::string proxy_host = "xx.xxx.xxx.xx";
        const std::string proxy_port = "3128";
        const std::string proxy_username = "username";
        const std::string proxy_password = "password";
        
        const std::string target_host = "google.com";
        const std::string target_port = "80"; // 若访问HTTPS则改为443
        
        // 1. 解析代理服务器地址
        boost::asio::ip::tcp::resolver resolver(io_context);
        boost::asio::ip::tcp::resolver::query proxy_query(
            proxy_host, 
            proxy_port, 
            boost::asio::ip::tcp::resolver::query::numeric_service
        );
        auto endpoint_iterator = resolver.resolve(proxy_query);
        
        // 2. 建立到代理的TCP连接
        boost::asio::ip::tcp::socket socket(io_context);
        boost::asio::connect(socket, endpoint_iterator);
        
        // 3. 构造带认证的CONNECT请求
        std::string auth_creds = proxy_username + ":" + proxy_password;
        std::string auth_header = "Proxy-Authorization: Basic " + base64_encode(auth_creds) + "\r\n";
        
        std::string connect_request = 
            "CONNECT " + target_host + ":" + target_port + " HTTP/1.1\r\n"
            "Host: " + target_host + ":" + target_port + "\r\n"
            + auth_header +
            "Connection: close\r\n\r\n";
        
        // 4. 发送CONNECT请求到代理
        boost::asio::write(socket, boost::asio::buffer(connect_request));
        
        // 5. 读取代理响应,确认连接成功
        boost::asio::streambuf response_buf;
        boost::asio::read_until(socket, response_buf, "\r\n");
        
        std::istream response_stream(&response_buf);
        std::string http_version;
        unsigned int status_code;
        std::string status_msg;
        
        response_stream >> http_version >> status_code;
        std::getline(response_stream, status_msg);
        
        if (http_version.substr(0, 5) != "HTTP/" || status_code != 200) {
            std::cerr << "代理连接失败: " << status_code << " " << status_msg << std::endl;
            return 1;
        }
        
        // 读取剩余的响应头
        boost::asio::read_until(socket, response_buf, "\r\n\r\n");
        
        // 6. 连接成功后,向目标服务器发送HTTP请求(示例为GET请求)
        std::string get_request = 
            "GET / HTTP/1.1\r\n"
            "Host: " + target_host + "\r\n"
            "Connection: close\r\n\r\n";
        
        boost::asio::write(socket, boost::asio::buffer(get_request));
        
        // 读取目标服务器响应
        char buffer[1024];
        while (true) {
            boost::system::error_code ec;
            size_t len = socket.read_some(boost::asio::buffer(buffer), ec);
            
            if (ec == boost::asio::error::eof) break;
            if (ec) throw boost::system::system_error(ec);
            
            std::cout.write(buffer, len);
        }
    } catch (std::exception& e) {
        std::cerr << "异常: " << e.what() << std::endl;
    }
    
    return 0;
}

关键说明

  • 代理地址解析:resolver::query仅需传入代理的IP/域名和端口,无需额外信息,这是你之前写法的核心错误。
  • 代理认证:通过在CONNECT请求中添加Proxy-Authorization头实现,需要将username:password进行Base64编码。
  • HTTPS支持:若目标是HTTPS服务器,在CONNECT成功后,需要使用boost::asio::ssl::stream包装socket,完成TLS握手后再发送HTTPS请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:35:07