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

使用Boost.Asio发起HTTPS GET请求时握手失败问题排查

问题分析与解决

核心错误原因

你遇到的握手错误packet length too long,根源是连接了错误的端口:代码中指定的端口是80,这是HTTP协议的默认端口,而HTTPS请求必须使用443端口。当你向80端口发送SSL握手请求时,服务器返回的是HTTP响应内容,SSL解析器无法识别,从而抛出数据包长度异常。

另外你怀疑的手动导入证书问题,Boost.Asio其实可以像curl一样自动加载系统根证书,不需要手动下载添加——ctx.set_default_verify_paths()调用已经会自动加载操作系统内置的信任根证书列表,和curl的行为一致。

修正后的代码

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace http = boost::beast::http;
using tcp = boost::asio::ip::tcp;
namespace ssl = boost::asio::ssl;

int main()
{
    try {
        const std::string host = "api.binance.com";
        const std::string port = "443"; // 修正为HTTPS标准端口
        const std::string target = "/api/v3/time";

        boost::asio::io_context ioc;
        // 使用现代TLS客户端上下文,替代老旧的sslv23_client
        ssl::context ctx{ssl::context::tls_client};
        // 自动加载系统根证书,无需手动导入
        ctx.set_default_verify_paths();
        // 显式启用证书验证(默认已开启,写出更清晰)
        ctx.set_verify_mode(ssl::verify_peer);

        tcp::resolver resolver{ioc};
        ssl::stream<tcp::socket> stream{ioc, ctx};

        // 设置SNI主机名,现代HTTPS服务器要求的必要步骤
        if(!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) {
            boost::system::error_code ec{static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category()};
            throw boost::system::system_error{ec};
        }

        const auto result = resolver.resolve(host, port);
        boost::asio::connect(stream.next_layer(), result.begin(), result.end());
        stream.handshake(ssl::stream_base::client);

        http::request<http::string_body> req{http::verb::get, target, 11}; // 使用HTTP/1.1
        req.set(http::field::host, host);
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

        http::write(stream, req);

        boost::beast::flat_buffer buffer;
        http::response<http::dynamic_body> res;
        http::read(stream, buffer, res);

        std::cout << res << std::endl;

        boost::system::error_code ec;
        stream.shutdown(ec);
        // 忽略正常的EOF和未连接错误
        if (ec && ec != boost::asio::error::eof && ec != boost::system::errc::not_connected) {
            throw boost::system::system_error{ec};
        }
    } catch(const std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

关键改动说明

  • 端口修正:将port从80改为443,适配HTTPS协议的标准端口。
  • SSL上下文优化:使用tls_client替代老旧的sslv23_client,兼容现代TLS协议版本。
  • 移除手动证书加载:依赖set_default_verify_paths()自动加载系统根证书,和curl行为完全一致。
  • 添加SNI设置:调用SSL_set_tlsext_host_name设置服务器名称指示,确保多域名服务器能返回正确的证书。
  • HTTP版本更新:将请求版本从10(HTTP/1.0)改为11(HTTP/1.1),符合现代服务器规范。

验证效果

编译运行修正后的代码,会得到和curl一致的返回结果:

{"serverTime":1679237703479}

内容的提问来源于stack exchange,提问作者Freddy Martinez Garcia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:53:11