-
-
Save ra1u/1e3cf085f680c0901bb92668254e996b to your computer and use it in GitHub Desktop.
beast pipelined client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/asio/connect.hpp> | |
#include <boost/asio/ip/tcp.hpp> | |
#include <boost/beast/core.hpp> | |
#include <boost/beast/http.hpp> | |
#include <boost/beast/version.hpp> | |
#include <cstdlib> | |
#include <functional> | |
#include <iostream> | |
#include <memory> | |
#include <string> | |
namespace { | |
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> | |
namespace http = boost::beast::http; // from <boost/beast/http.hpp> | |
//------------------------------------------------------------------------------ | |
std::shared_ptr<http::request<http::string_body>> make_req(const std::string &body) | |
{ | |
auto r = std::make_shared<http::request<http::string_body>>(); | |
r->version(11); | |
r->method(http::verb::put); | |
r->target("/"); | |
r->body() = body; | |
r->prepare_payload(); | |
return r; | |
} | |
// Report a failure | |
void fail(boost::system::error_code ec, char const *what) | |
{ | |
std::cerr << what << ": " << ec.message() << "\n"; | |
} | |
// Performs an HTTP GET and prints the response | |
class session : public std::enable_shared_from_this<session> { | |
tcp::resolver resolver_; | |
tcp::socket socket_; | |
boost::beast::flat_buffer buffer_; | |
int& counter_; | |
public: | |
// Resolver and socket require an io_context | |
explicit session(boost::asio::io_context &ioc,int& cnt) | |
: resolver_(ioc), socket_(ioc), counter_(cnt) | |
{ | |
} | |
// Start the asynchronous operation | |
void run(char const *host, char const *port, char const *target, | |
int version) | |
{ | |
// Look up the domain name | |
resolver_.async_resolve( | |
host, port, | |
std::bind(&session::on_resolve, shared_from_this(), | |
std::placeholders::_1, std::placeholders::_2)); | |
} | |
void on_resolve(boost::system::error_code ec, | |
tcp::resolver::results_type results) | |
{ | |
if (ec) | |
return fail(ec, "resolve"); | |
// Make the connection on the IP address we get from a lookup | |
boost::asio::async_connect(socket_, results.begin(), results.end(), | |
std::bind(&session::on_connect, | |
shared_from_this(), | |
std::placeholders::_1)); | |
} | |
void on_connect(boost::system::error_code ec) | |
{ | |
if (ec) | |
return fail(ec, "connect"); | |
send_msg(); | |
} | |
void send_msg() | |
{ | |
// Send the HTTP request to the remote host | |
auto self = shared_from_this(); | |
auto reqp = make_req(std::to_string(counter_)); | |
const auto& req = *reqp; | |
http::async_write(socket_, req, | |
[self, this,reqp](boost::system::error_code ec, | |
std::size_t bytes_transferred) { | |
on_write(ec, bytes_transferred); | |
}); | |
} | |
void on_write(boost::system::error_code ec, std::size_t bytes_transferred) | |
{ | |
boost::ignore_unused(bytes_transferred); | |
if (ec) | |
return fail(ec, "write"); | |
--counter_; | |
// Receive the HTTP response | |
//auto buffp = std::make_shared<boost::beast::flat_buffer>(); | |
auto resp = std::make_shared<http::response<http::string_body>>(); | |
auto self = shared_from_this(); | |
http::async_read( | |
socket_, buffer_, *resp, | |
[self, this, resp](boost::system::error_code ec, | |
std::size_t bytes_transferred) { | |
on_read(ec, bytes_transferred, *resp); | |
}); | |
if (counter_ > 0) { | |
send_msg(); | |
} | |
} | |
void on_read(boost::system::error_code ec, std::size_t bytes_transferred, | |
http::response<http::string_body> &res) | |
{ | |
boost::ignore_unused(bytes_transferred); | |
if (ec) | |
return fail(ec, "read"); | |
// Write the message to standard out | |
std::cout << res.body() << std::endl; | |
} | |
}; | |
//------------------------------------------------------------------------------ | |
static int mainf(int argc, char **argv) | |
{ | |
// Check command line arguments. | |
int N = (argc >= 2) ? std::stoi(argv[1]) : 1; | |
auto const host = "localhost"; | |
auto const port = "8080"; | |
auto const target = "/"; | |
int version = 11; | |
// The io_context is required for all I/O | |
boost::asio::io_context ioc; | |
// Launch the asynchronous operation | |
std::make_shared<session>(ioc,N)->run(host, port, target, version); | |
// Run the I/O service. The call will return when | |
// the get operation is complete. | |
ioc.run(); | |
return EXIT_SUCCESS; | |
} | |
} // namespace | |
int main(int argc, char **argv) | |
{ | |
return mainf(argc, argv); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment