Skip to content

Instantly share code, notes, and snippets.

@ra1u

ra1u/client.cpp Secret

Created March 19, 2019 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ra1u/1e3cf085f680c0901bb92668254e996b to your computer and use it in GitHub Desktop.
Save ra1u/1e3cf085f680c0901bb92668254e996b to your computer and use it in GitHub Desktop.
beast pipelined client
#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