gpt4 book ai didi

c++ - 简单的 boost ASIO https 不返回正文

转载 作者:行者123 更新时间:2023-11-30 02:19:02 26 4
gpt4 key购买 nike

我正在尝试使用 boost 示例 HTTPS 客户端,但是,使用路径/向 google.com 发送一个简单的获取请求没有返回正文。

输出:

Verifying /OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
Verifying /C=US/O=Google Trust Services/CN=Google Internet Authority G3
Verifying /C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
Handshake OK
Request:
GET / HTTP/1.1
Host: www.google.com
Accept: */*
Connection: close


Reply: HTTP/1.1 200 OK
Date: Thu, 12 Jul 2018 04:23:20 GMT
Expires: -1
Cache

奇怪的是,它在缓存处中断了。这是代码:

#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/asio/ssl.hpp>

using boost::asio::ip::tcp;

#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")

enum { max_length = 10000 };

class client
{
public:
client(boost::asio::io_service& io_service,
boost::asio::ssl::context& context,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service, context)
{
socket_.set_verify_mode(boost::asio::ssl::verify_peer);
socket_.set_verify_callback(
boost::bind(&client::verify_certificate, this, _1, _2));

std::ostream request_stream(&request_);
request_stream << "GET / HTTP/1.1\r\n";
request_stream << "Host: www.google.com\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";


boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&client::handle_connect, this,
boost::asio::placeholders::error));


}

bool verify_certificate(bool preverified,
boost::asio::ssl::verify_context& ctx)
{
// The verify callback can be used to check whether the certificate that is
// being presented is valid for the peer. For example, RFC 2818 describes
// the steps involved in doing this for HTTPS. Consult the OpenSSL
// documentation for more details. Note that the callback is called once
// for each certificate in the certificate chain, starting from the root
// certificate authority.

// In this example we will simply print the certificate's subject name.
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying " << subject_name << "\n";

return preverified;
}

void handle_connect(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&client::handle_handshake, this,
boost::asio::placeholders::error));
}
else
{
std::cout << "Connect failed: " << error.message() << "\n";
}
}

void handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
std::cout << "Handshake OK " << "\n";
std::cout << "Request: " << "\n";
const char* header = boost::asio::buffer_cast<const char*>(request_.data());
std::cout << header << "\n";


boost::asio::async_write(socket_,
request_,
boost::bind(&client::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Handshake failed: " << error.message() << "\n";
}
}

void handle_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_read(socket_,
boost::asio::buffer(reply_, bytes_transferred),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Write failed: " << error.message() << "\n";
}
}

void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
std::cout << "Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
}
else
{
std::cout << "Read failed: " << error.message() << "\n";
}
}

private:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
char reply_[max_length];
boost::asio::streambuf request_;
};

void add_windows_root_certs(boost::asio::ssl::context &ctx)
{
HCERTSTORE hStore = CertOpenSystemStore(0, L"ROOT");
if (hStore == NULL) {
return;
}

X509_STORE *store = X509_STORE_new();
PCCERT_CONTEXT pContext = NULL;
while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
// convert from DER to internal format
X509 *x509 = d2i_X509(NULL,
(const unsigned char **)&pContext->pbCertEncoded,
pContext->cbCertEncoded);
if (x509 != NULL) {
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
}

CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);

// attach X509_STORE to boost ssl context
SSL_CTX_set_cert_store(ctx.native_handle(), store);
}

int main(int argc, char* argv[])
{
try
{
namespace ssl = boost::asio::ssl;

boost::asio::io_service io_service;

boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query("www.google.com", "443");
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

ssl::context ctx(ssl::context::tlsv12_client);


add_windows_root_certs(ctx);
ctx.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert);

// use custom verify_callback here for debugging purposes

client c(io_service, ctx, iterator);

io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}

system("pause");

return 0;
}

连接成功,我在Wireshark中监控,是真正的SSL连接,我指定的是HTTP/1.1。不知道我在这里错过了什么。

最佳答案

    boost::asio::async_read(socket_,
boost::asio::buffer(reply_, bytes_transferred),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

您告诉读取函数缓冲区的大小是 bytes_transferred。那是胡说八道。

使用足够大的缓冲区,重复读取使用boost::asio::streambuf

哦。并考虑将 Boost Beast 用于 HTTP 请求

关于c++ - 简单的 boost ASIO https 不返回正文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51304443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com