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

使用libnghttp2-asio连接reddit遇tls协议协商失败问题求解

解决libnghttp2-asio连接reddit时的TLS协议协商错误

出现error: tls: no application protocol negotiated错误的核心原因是缺少HTTP/2协议的ALPN协商配置。libnghttp2-asio是面向HTTP/2的库,TLS握手阶段必须通过ALPN(应用层协议协商)向服务器明确指定使用h2(HTTP/2 over TLS)协议,原代码未配置该步骤,导致服务器无法确定应用层协议,握手失败。

解决步骤

  • 给SSL上下文添加ALPN协议配置,指定支持h2协议
  • 连接成功后发起HTTP/2请求(否则连接会被服务器主动关闭,且无法获取网页内容)

修改后的完整代码

#include <iostream>
#include <boost/asio.hpp>
#include <nghttp2/asio_http2_client.h>

int main() {
    boost::system::error_code ec;
    namespace net = nghttp2::asio_http2;
    namespace ssl = boost::asio::ssl;
    using boost::asio::ip::tcp;

    boost::asio::io_context ioc;

    ssl::context tls(ssl::context::tlsv12_client);
    tls.set_options(ssl::context::default_workarounds);
    tls.set_verify_mode(ssl::verify_none);
    tls.set_default_verify_paths();

    // 配置ALPN协议,指定使用HTTP/2(h2)
    // ALPN格式:每个协议名前加1字节的长度前缀,h2的长度为2
    std::string alpn_protos = "\x02h2";
    tls.set_alpn_protos(alpn_protos.data(), alpn_protos.size(), ec);
    if (ec) {
        std::cout << "设置ALPN协议失败: " << ec.message() << std::endl;
        return 1;
    }

    net::client::session session(ioc, tls, "www.reddit.com", "443");

    session.on_connect([&session](tcp::resolver::iterator endpoint_it) {
        std::cout << "已连接" << std::endl;

        // 发起HTTP/2 GET请求
        boost::system::error_code req_ec;
        auto req = session.submit(
            req_ec, "GET", "/",
            [](const net::client::response& res) {
                // 输出响应状态码
                std::cout << "\n响应状态码: " << res.status_code() << std::endl;

                // 读取并输出响应体内容
                res.on_data([](const uint8_t* data, std::size_t len) {
                    std::cout.write(reinterpret_cast<const char*>(data), len);
                });
            },
            {{"Host", "www.reddit.com"}, {"Accept", "*/*"}});

        if (req_ec) {
            std::cout << "提交请求失败: " << req_ec.message() << std::endl;
        }
    });

    session.on_error([](const boost::system::error_code& ec) {
        std::cout << "错误: " << ec.message() << std::endl;
    });

    ioc.run();

    return 0;
}

关键修改说明

  1. ALPN配置:std::string alpn_protos = "\x02h2"遵循ALPN协议格式,用1字节的\x02表示后续协议名h2的长度,通过tls.set_alpn_protos将其注入SSL上下文,让TLS握手时协商使用HTTP/2。
  2. 发起请求:在on_connect回调中调用session.submit发送GET请求,这是获取网页内容的必要操作,同时避免连接建立后被服务器无请求闲置关闭。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:33:20