是否可以将 keep-alive 与 boost::beast 同步 https 客户端一起使用?

发布于 2025-01-11 19:06:46 字数 2750 浏览 0 评论 0原文

使用同步 ssl 客户端时,是否可以将 http 1.1 keep-alive 与 boosteast 库一起使用?我有一个类似如下的流程:

  1. 使用 https 连接到 Web 服务器。发送初始请求,等待
  2. https 本机套接字句柄上的响应 select()/epoll()/etc
  3. 当本机句柄准备就绪时,我在 ssl_stream

第一个 http::read() 工作得很好。但是,当套接字下次准备好时,在套接字上发出 http::read() 时会出现流结束异常。我想要的是套接字对于多个请求保持活动状态。

代码并不太复杂,但它是分成几部分的:

         if( native_socket_for_https_connection_ready ) {                                                                                                                                                                                                                                                                                             
              boost::beast::http::response<boost::beast::http::dynamic_body> res;                                                                                                                                                                                                                                                                                                                                     
              boost::beast::http::read( m_HTTPSConnection, m_HTTPSBuffer, res, ec );                                                                                                                       
                                                                                                                                                                                                           
              std::cout << "Https Connection Response: " << res << std::endl;                                                                                                                              
              std::cout << "Keep-Alive Result: " << res.keep_alive() << std::endl;                                                                                                                         
                                                                                                                                                                                                           
              m_HTTPSBuffer.clear();                                                                                                                                                                       
          } 

其中,m_HTTPSConnectionboost::beast::ssl_stream,并且m_HTTPSBuffer 是一个flat_buffer。唯一的其他细节是本机套接字的提取。

我正在尝试将从安全套接字读取数据放入不使用异步 I/O 的遗留应用程序中——我希望 http::read() 上的后续读取能够完成并且不会引发异常。

Is it possible to use http 1.1 keep-alive with the boost beast library when using a sync ssl client? I have a process that works something like this:

  1. Connection to web server using https. Send an initial request, wait for a response
  2. select()/epoll()/etc on the https native socket handle
  3. When the native handle has something ready, I issue an http::read() on the ssl_stream<beast::tcp_stream>.

The first http::read() works perfectly fine. However, when the socket is ready the next time, I get an end of stream exception when issuing an http::read() on the socket. What I want is for the socket to stay alive for multiple requests.

The code isn't too complicated, but it's in pieces:

         if( native_socket_for_https_connection_ready ) {                                                                                                                                                                                                                                                                                             
              boost::beast::http::response<boost::beast::http::dynamic_body> res;                                                                                                                                                                                                                                                                                                                                     
              boost::beast::http::read( m_HTTPSConnection, m_HTTPSBuffer, res, ec );                                                                                                                       
                                                                                                                                                                                                           
              std::cout << "Https Connection Response: " << res << std::endl;                                                                                                                              
              std::cout << "Keep-Alive Result: " << res.keep_alive() << std::endl;                                                                                                                         
                                                                                                                                                                                                           
              m_HTTPSBuffer.clear();                                                                                                                                                                       
          } 

Where, m_HTTPSConnection is a boost::beast::ssl_stream<boost::beast::tcp_stream>, and m_HTTPSBuffer is a flat_buffer. The only other detail is the extraction of the native socket.

I am trying to fit reading from a secure socket into a legacy application that is not using async I/O -- I want the subsequent reads on http::read() to complete and not throw an exception.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

等风也等你 2025-01-18 19:06:46

服务器可能会断开连接,例如,当您的请求可能具有不确定的内容长度时,从而无法保持连接打开(服务器如何知道请求不完整?)。

所以,想象一些更完整的代码:

1a。使用 https

ssl::context ctx(ssl::context::sslv23);
beast::ssl_stream<beast::tcp_stream> s(ioc, ctx);
s.next_layer().connect({address_v4{{34, 227, 133, 25}}, 443});
s.handshake(ssl::stream_base::handshake_type::client);

1b 连接到 Web 服务器。发送初始请求

http::request<http::string_body> req(http::verb::post, "/post", 10,
                                     R"~({"data":42})~");
req.set(http::field::host, "httpbin.org");
req.keep_alive(true); // no difference on HTTP/1.1+
req.prepare_payload();
write(s, req);

2. 然后等待响应(select/epoll):

std::future<void> ready = s.next_layer().socket().async_wait(
    net::socket_base::wait_type::wait_read, net::use_future);
ready.wait();

(显然,这可以通过基于 native_handle() 的外部代码来完成)

3. 在流上读取问题

http::response<http::dynamic_body> res;
beast::flat_buffer                 buf;
http::read(s, buf, res);

这一切都运行良好:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <iostream>

namespace net   = boost::asio;
namespace beast = boost::beast;
namespace http  = beast::http;
namespace ssl   = net::ssl;
using boost::system::error_code;
using net::ip::address_v4;
using net::ip::tcp;

using namespace std::chrono_literals;
using std::this_thread::sleep_for;
static auto now = std::chrono::steady_clock::now;

int main() {
    net::thread_pool ioc;

    // connection to web server using https
    ssl::context ctx(ssl::context::sslv23);
    beast::ssl_stream<beast::tcp_stream> s(ioc, ctx);
    s.next_layer().connect({address_v4{{34, 227, 133, 25}}, 443});
    s.handshake(ssl::stream_base::handshake_type::client);

    for (auto demo_end = now() + 1s; now() <= demo_end; sleep_for(10ms)) {
        // send an initial request
        http::request<http::string_body> req(http::verb::post, "/post", 10,
                                             R"~({"data":42})~");
        req.set(http::field::host, "httpbin.org");
        req.keep_alive(true); // no difference on HTTP/1.1+
        req.prepare_payload();
        write(s, req);

        // wait for a response
        // (obviously, this can be done by external code based on the
        // native_handle() instead)
        std::future<void> ready = s.next_layer().socket().async_wait(
            net::socket_base::wait_type::wait_read, net::use_future);
        ready.wait();

        // issue read on the stream
        http::response<http::dynamic_body> res;
        beast::flat_buffer                 buf;
        http::read(s, buf, res);

        std::cout << "Https Connection Response: " << res << std::endl;
        std::cout << "Keep-Alive Result: " << res.keep_alive() << std::endl;
        if (!res.keep_alive())
            break;
    }

    // bye
    ioc.join();
}

打印

Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-124910e0751e35dd54340615"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-5fa263b33e2cc5937d6204a5"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-0430cdac1b7924210e9ea13d"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-7683e03c727619fc5e5db850"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-5c733376197f2e0d68afb4c8"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-604db5aa0f4abccc4c721740"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-3ea4400e52caa293041cd83f"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-05d2949e37556119199d2627"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-57e377492da2d9f26c205699"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-526a207d11c3aa9d231ec537"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-64f2d0df238d5d14388390db"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-1612613c2520b2a908706e58"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-00d80af2769dbc023e8ab652"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-505398b91878748a45d04795"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-087616e737a56957076e0a9c"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-31987540136993062764c373"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-37efb18d7fdc07ef1d4051cf"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-666c753e62ff049e375253d3"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-524b4fea230a31273a1264e6"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-4352dd83652fa4d74d8910e8"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-36f9eb3918e3fbf215e0c5a7"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1

This file can be also found using the Coliru command line: cat /Archive2/c2/f4e2478d335b42/main.cpp

The server could be dropping the connection, e.g. when your request maybe of indeterminate content-length, making it impossible to keep the connection open (how would the server know that the request was incomplete?).

So, just imagining some more complete code:

1a. connection to web server using https

ssl::context ctx(ssl::context::sslv23);
beast::ssl_stream<beast::tcp_stream> s(ioc, ctx);
s.next_layer().connect({address_v4{{34, 227, 133, 25}}, 443});
s.handshake(ssl::stream_base::handshake_type::client);

1b. send an initial request

http::request<http::string_body> req(http::verb::post, "/post", 10,
                                     R"~({"data":42})~");
req.set(http::field::host, "httpbin.org");
req.keep_alive(true); // no difference on HTTP/1.1+
req.prepare_payload();
write(s, req);

2. Then wait for a response (select/epoll):

std::future<void> ready = s.next_layer().socket().async_wait(
    net::socket_base::wait_type::wait_read, net::use_future);
ready.wait();

(obviously, this can be done by external code based on the native_handle() instead)

3. Issue read on the stream

http::response<http::dynamic_body> res;
beast::flat_buffer                 buf;
http::read(s, buf, res);

It all works nicely:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <iostream>

namespace net   = boost::asio;
namespace beast = boost::beast;
namespace http  = beast::http;
namespace ssl   = net::ssl;
using boost::system::error_code;
using net::ip::address_v4;
using net::ip::tcp;

using namespace std::chrono_literals;
using std::this_thread::sleep_for;
static auto now = std::chrono::steady_clock::now;

int main() {
    net::thread_pool ioc;

    // connection to web server using https
    ssl::context ctx(ssl::context::sslv23);
    beast::ssl_stream<beast::tcp_stream> s(ioc, ctx);
    s.next_layer().connect({address_v4{{34, 227, 133, 25}}, 443});
    s.handshake(ssl::stream_base::handshake_type::client);

    for (auto demo_end = now() + 1s; now() <= demo_end; sleep_for(10ms)) {
        // send an initial request
        http::request<http::string_body> req(http::verb::post, "/post", 10,
                                             R"~({"data":42})~");
        req.set(http::field::host, "httpbin.org");
        req.keep_alive(true); // no difference on HTTP/1.1+
        req.prepare_payload();
        write(s, req);

        // wait for a response
        // (obviously, this can be done by external code based on the
        // native_handle() instead)
        std::future<void> ready = s.next_layer().socket().async_wait(
            net::socket_base::wait_type::wait_read, net::use_future);
        ready.wait();

        // issue read on the stream
        http::response<http::dynamic_body> res;
        beast::flat_buffer                 buf;
        http::read(s, buf, res);

        std::cout << "Https Connection Response: " << res << std::endl;
        std::cout << "Keep-Alive Result: " << res.keep_alive() << std::endl;
        if (!res.keep_alive())
            break;
    }

    // bye
    ioc.join();
}

Prints

Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-124910e0751e35dd54340615"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-5fa263b33e2cc5937d6204a5"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-0430cdac1b7924210e9ea13d"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-7683e03c727619fc5e5db850"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-5c733376197f2e0d68afb4c8"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-604db5aa0f4abccc4c721740"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:50 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00a-3ea4400e52caa293041cd83f"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-05d2949e37556119199d2627"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-57e377492da2d9f26c205699"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-526a207d11c3aa9d231ec537"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-64f2d0df238d5d14388390db"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-1612613c2520b2a908706e58"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-00d80af2769dbc023e8ab652"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-505398b91878748a45d04795"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-087616e737a56957076e0a9c"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-31987540136993062764c373"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-37efb18d7fdc07ef1d4051cf"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-666c753e62ff049e375253d3"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-524b4fea230a31273a1264e6"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-4352dd83652fa4d74d8910e8"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1
Https Connection Response: HTTP/1.1 200 OK
Date: Thu, 03 Mar 2022 16:42:51 GMT
Content-Type: application/json
Content-Length: 321
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "args": {}, 
  "data": "{\"data\":42}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Content-Length": "11", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6220f00b-36f9eb3918e3fbf215e0c5a7"
  }, 
  "json": {
    "data": 42
  }, 
  "origin": "173.203.57.63", 
  "url": "https://httpbin.org/post"
}

Keep-Alive Result: 1

This file can be also found using the Coliru command line: cat /Archive2/c2/f4e2478d335b42/main.cpp
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文