mirror of
https://github.com/boostorg/redis.git
synced 2026-01-19 04:42:09 +00:00
Simplifications.
This commit is contained in:
@@ -12,17 +12,25 @@
|
||||
namespace aedis {
|
||||
namespace adapter {
|
||||
|
||||
/** \brief Creates a void response adapter.
|
||||
/** \brief Creates a dummy response adapter.
|
||||
\ingroup any
|
||||
|
||||
The adapter returned by this function ignores responses and is
|
||||
useful to avoid wasting time with responses on which the user is
|
||||
not insterested in.
|
||||
|
||||
Example usage:
|
||||
The adapter returned by this function is dummy which means it
|
||||
ignores responses. It is useful to avoid wasting time with
|
||||
responses which are not needed. For example
|
||||
|
||||
@code
|
||||
co_await async_read(socket, buffer, adapt());
|
||||
// Pushes and writes some commands to the server.
|
||||
sr.push(command::hello, 3);
|
||||
sr.push(command::ping);
|
||||
sr.push(command::quit);
|
||||
net::write(socket, net::buffer(request));
|
||||
|
||||
// Ignores all responses except for the response to ping.
|
||||
std::string buffer;
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt()); // hello
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt(resp)); // ping
|
||||
resp3::read(socket, dynamic_buffer(buffer, adapt())); // quit
|
||||
@endcode
|
||||
*/
|
||||
inline
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <aedis/resp3/node.hpp>
|
||||
#include <aedis/adapter/error.hpp>
|
||||
|
||||
// TODO: Add an adapter for float and double, from spirit.
|
||||
|
||||
namespace aedis {
|
||||
namespace adapter {
|
||||
namespace detail {
|
||||
|
||||
@@ -96,94 +96,27 @@ struct assigner<0> {
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct assigner2 {
|
||||
template <class T1, class T2>
|
||||
static void assign(T1& dest, T2& from)
|
||||
{
|
||||
std::get<N>(dest) = internal_adapt(std::get<N>(from));
|
||||
assigner2<N - 1>::assign(dest, from);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct assigner2<0> {
|
||||
template <class T1, class T2>
|
||||
static void assign(T1& dest, T2& from)
|
||||
{
|
||||
std::get<0>(dest) = internal_adapt(std::get<0>(from));
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
/** @brief Return a specific adapter from the tuple.
|
||||
*
|
||||
* \param t A tuple of response adapters.
|
||||
* \return The adapter that corresponds to type T.
|
||||
*/
|
||||
template <class T, class Tuple>
|
||||
auto& get(Tuple& t)
|
||||
{
|
||||
return std::get<typename response_traits<T>::adapter_type>(t);
|
||||
}
|
||||
|
||||
template <class Tuple>
|
||||
using adapters_array_t =
|
||||
std::array<
|
||||
boost::mp11::mp_unique<
|
||||
boost::mp11::mp_rename<
|
||||
boost::mp11::mp_transform<
|
||||
adapter_t, Tuple>,
|
||||
boost::variant2::variant>>,
|
||||
std::tuple_size<Tuple>::value>;
|
||||
|
||||
template <class Tuple>
|
||||
adapters_array_t<Tuple> make_adapters_array(Tuple& t)
|
||||
{
|
||||
adapters_array_t<Tuple> ret;
|
||||
detail::assigner<std::tuple_size<Tuple>::value - 1>::assign(ret, t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Transaforms a tuple of responses.
|
||||
*
|
||||
* @return Transaforms a tuple of responses into a tuple of adapters.
|
||||
*/
|
||||
template <class Tuple>
|
||||
using adapters_tuple_t =
|
||||
boost::mp11::mp_rename<
|
||||
boost::mp11::mp_transform<
|
||||
adapter_t, Tuple>,
|
||||
std::tuple>;
|
||||
|
||||
/** @brief Make a tuple of adapters.
|
||||
*
|
||||
* \param t Tuple of responses.
|
||||
* \return Tuple of adapters.
|
||||
*/
|
||||
template <class Tuple>
|
||||
auto
|
||||
make_adapters_tuple(Tuple& t)
|
||||
{
|
||||
adapters_tuple_t<Tuple> ret;
|
||||
detail::assigner2<std::tuple_size<Tuple>::value - 1>::assign(ret, t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Tuple>
|
||||
class static_aggregate_adapter {
|
||||
private:
|
||||
using adapters_array_type =
|
||||
std::array<
|
||||
boost::mp11::mp_unique<
|
||||
boost::mp11::mp_rename<
|
||||
boost::mp11::mp_transform<
|
||||
adapter_t, Tuple>,
|
||||
boost::variant2::variant>>,
|
||||
std::tuple_size<Tuple>::value>;
|
||||
|
||||
std::size_t i_ = 0;
|
||||
std::size_t aggregate_size_ = 0;
|
||||
adapters_array_t<Tuple> adapters_;
|
||||
adapters_array_type adapters_;
|
||||
|
||||
public:
|
||||
static_aggregate_adapter(Tuple* r = nullptr)
|
||||
: adapters_(make_adapters_array(*r))
|
||||
{}
|
||||
{
|
||||
detail::assigner<std::tuple_size<Tuple>::value - 1>::assign(adapters_, *r);
|
||||
}
|
||||
|
||||
void count(resp3::node<boost::string_view> const& nd)
|
||||
{
|
||||
|
||||
@@ -61,17 +61,19 @@
|
||||
tcp_socket socket{co_await net::this_coro::executor};
|
||||
co_await socket.async_connect(ep);
|
||||
|
||||
std::string request, read_buffer, response;
|
||||
std::string buffer, response;
|
||||
|
||||
auto sr = make_serializer(request);
|
||||
sr.push(command::hello, 3);
|
||||
sr.push(command::set, "key", "Value", "EX", "2", "get");
|
||||
sr.push(command::quit);
|
||||
co_await net::async_write(socket, net::buffer(request));
|
||||
co_await net::async_write(socket, net::buffer(buffer));
|
||||
buffer.clear();
|
||||
|
||||
co_await resp3::async_read(socket, dynamic_buffer(read_buffer)); // Hello (ignored).
|
||||
co_await resp3::async_read(socket, dynamic_buffer(read_buffer), adapt(response)); // Set
|
||||
co_await resp3::async_read(socket, dynamic_buffer(read_buffer)); // Quit (ignored)
|
||||
auto dbuffer = net::dynamic_buffer(read_buffer);
|
||||
co_await resp3::async_read(socket, dbuffer); // Hello ignored.
|
||||
co_await resp3::async_read(socket, dbuffer, adapt(response)); // Set
|
||||
co_await resp3::async_read(socket, dbuffer); // Quit ignored.
|
||||
|
||||
co_return response;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
// TODO: What to do if users send a discard command not contained in a
|
||||
// transaction. The client object will try to pop the queue until a
|
||||
// multi is found.
|
||||
//
|
||||
// TODO: Pass max_size as a config parameter to the dynamic buffer.
|
||||
|
||||
namespace aedis {
|
||||
namespace generic {
|
||||
@@ -267,6 +269,7 @@ private:
|
||||
std::string requests_;
|
||||
|
||||
// The commands contained in the requests.
|
||||
// TODO: also keep the keys in addition to the commands.
|
||||
std::vector<Command> commands_;
|
||||
|
||||
// Info about the requests.
|
||||
|
||||
@@ -170,7 +170,7 @@ struct read_op {
|
||||
}
|
||||
|
||||
assert(!cli->read_buffer_.empty());
|
||||
t = resp3::detail::to_type(cli->read_buffer_.front());
|
||||
t = resp3::to_type(cli->read_buffer_.front());
|
||||
cmd = Command::invalid;
|
||||
if (t != resp3::type::push) {
|
||||
assert(!cli->commands_.empty());
|
||||
|
||||
@@ -22,29 +22,6 @@ std::size_t parse_uint(char const* data, std::size_t size, boost::system::error_
|
||||
return ret;
|
||||
}
|
||||
|
||||
type to_type(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case '!': return type::blob_error;
|
||||
case '=': return type::verbatim_string;
|
||||
case '$': return type::blob_string;
|
||||
case ';': return type::streamed_string_part;
|
||||
case '-': return type::simple_error;
|
||||
case ':': return type::number;
|
||||
case ',': return type::doublean;
|
||||
case '#': return type::boolean;
|
||||
case '(': return type::big_number;
|
||||
case '+': return type::simple_string;
|
||||
case '_': return type::null;
|
||||
case '>': return type::push;
|
||||
case '~': return type::set;
|
||||
case '*': return type::array;
|
||||
case '|': return type::attribute;
|
||||
case '%': return type::map;
|
||||
default: return type::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // resp3
|
||||
} // aedis
|
||||
|
||||
@@ -24,9 +24,6 @@ namespace detail {
|
||||
|
||||
std::size_t parse_uint(char const* data, std::size_t size, boost::system::error_code& ec);
|
||||
|
||||
// Converts a wire-format RESP3 type (char) to a resp3 type.
|
||||
type to_type(char c);
|
||||
|
||||
template <class ResponseAdapter>
|
||||
class parser {
|
||||
private:
|
||||
|
||||
@@ -90,5 +90,28 @@ char to_code(type t)
|
||||
}
|
||||
}
|
||||
|
||||
type to_type(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case '!': return type::blob_error;
|
||||
case '=': return type::verbatim_string;
|
||||
case '$': return type::blob_string;
|
||||
case ';': return type::streamed_string_part;
|
||||
case '-': return type::simple_error;
|
||||
case ':': return type::number;
|
||||
case ',': return type::doublean;
|
||||
case '#': return type::boolean;
|
||||
case '(': return type::big_number;
|
||||
case '+': return type::simple_string;
|
||||
case '_': return type::null;
|
||||
case '>': return type::push;
|
||||
case '~': return type::set;
|
||||
case '*': return type::array;
|
||||
case '|': return type::attribute;
|
||||
case '%': return type::map;
|
||||
default: return type::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
} // resp3
|
||||
} // aedis
|
||||
|
||||
@@ -86,13 +86,11 @@ bool is_aggregate(type t);
|
||||
*/
|
||||
std::size_t element_multiplicity(type t);
|
||||
|
||||
/** @brief Returns the wire code of a given type.
|
||||
* @ingroup any
|
||||
*
|
||||
* @param t The RESP3 type.
|
||||
* @return The code (\c char) that identifies the data type on the wire.
|
||||
*/
|
||||
// Returns the wire code of a given type.
|
||||
char to_code(type t);
|
||||
|
||||
// Converts a wire-format RESP3 type (char) to a resp3 type.
|
||||
type to_type(char c);
|
||||
|
||||
} // resp3
|
||||
} // aedis
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
namespace net = boost::asio;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::redis::command;
|
||||
using client_type = aedis::generic::client<net::ip::tcp::socket, command>;
|
||||
using aedis::generic::client;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using response_type = std::vector<node<std::string>>;
|
||||
using adapter_type = aedis::adapter::adapter_t<response_type>;
|
||||
|
||||
// Prints aggregates that don't contain any nested aggregates.
|
||||
void print_aggregate(response_type const& v)
|
||||
@@ -96,7 +98,7 @@ public:
|
||||
|
||||
private:
|
||||
response_type resp_;
|
||||
adapter_type adapter_;
|
||||
adapter_t<response_type> adapter_;
|
||||
client_type* db_;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
namespace net = boost::asio;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::redis::command;
|
||||
using aedis::generic::client;
|
||||
using aedis::user_session;
|
||||
using aedis::user_session_base;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using response_type = std::vector<node<std::string>>;
|
||||
using adapter_type = aedis::adapter::adapter_t<response_type>;
|
||||
|
||||
class receiver {
|
||||
public:
|
||||
@@ -78,7 +79,7 @@ public:
|
||||
|
||||
private:
|
||||
response_type resp_;
|
||||
adapter_type adapter_;
|
||||
adapter_t<response_type> adapter_;
|
||||
std::shared_ptr<client_type> db_;
|
||||
std::vector<std::shared_ptr<user_session_base>> sessions_;
|
||||
};
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
namespace net = boost::asio;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::redis::command;
|
||||
using aedis::generic::client;
|
||||
using aedis::user_session;
|
||||
using aedis::user_session_base;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using response_type = std::vector<node<std::string>>;
|
||||
using adapter_type = aedis::adapter::adapter_t<response_type>;
|
||||
|
||||
class receiver {
|
||||
public:
|
||||
@@ -76,7 +77,7 @@ public:
|
||||
|
||||
private:
|
||||
response_type resp_;
|
||||
adapter_type adapter_;
|
||||
adapter_t<response_type> adapter_;
|
||||
std::shared_ptr<client_type> db_;
|
||||
std::queue<std::shared_ptr<user_session_base>> sessions_;
|
||||
};
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::redis::command;
|
||||
using aedis::generic::client;
|
||||
using aedis::adapter::adapt;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using response_type = node<std::string>;
|
||||
using adapter_type = aedis::adapter::adapter_t<response_type>;
|
||||
|
||||
struct myreceiver {
|
||||
public:
|
||||
@@ -61,7 +62,7 @@ public:
|
||||
|
||||
private:
|
||||
response_type resp_;
|
||||
adapter_type adapter_;
|
||||
adapter_t<response_type> adapter_;
|
||||
client_type* db_;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,20 +20,17 @@ struct mystruct {
|
||||
namespace net = boost::asio;
|
||||
namespace adapter = aedis::adapter;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapters_tuple_t;
|
||||
using aedis::adapter::make_adapters_tuple;
|
||||
using aedis::adapter::get;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::redis::command;
|
||||
using aedis::generic::client;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using responses_tuple_type =
|
||||
std::tuple<
|
||||
boost::optional<mystruct>,
|
||||
std::list<mystruct>,
|
||||
std::set<mystruct>,
|
||||
std::map<std::string, mystruct>
|
||||
>;
|
||||
using adapters_tuple_type = adapters_tuple_t<responses_tuple_type>;
|
||||
// Response types used in the example.
|
||||
using T0 = boost::optional<mystruct>;
|
||||
using T1 = std::list<mystruct>;
|
||||
using T2 = std::set<mystruct>;
|
||||
using T3 = std::map<std::string, mystruct>;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, mystruct const& obj)
|
||||
{
|
||||
@@ -64,7 +61,10 @@ void from_string(mystruct& obj, boost::string_view sv, boost::system::error_code
|
||||
class receiver {
|
||||
public:
|
||||
receiver(client_type& db)
|
||||
: adapters_(make_adapters_tuple(resps_))
|
||||
: adapter0_(adapt(resp0_))
|
||||
, adapter1_(adapt(resp1_))
|
||||
, adapter2_(adapt(resp2_))
|
||||
, adapter3_(adapt(resp3_))
|
||||
, db_{&db} {}
|
||||
|
||||
void on_connect()
|
||||
@@ -79,10 +79,10 @@ public:
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
switch (cmd) {
|
||||
case command::get: adapter::get<boost::optional<mystruct>>(adapters_)(nd, ec); break;
|
||||
case command::lrange: adapter::get<std::list<mystruct>>(adapters_)(nd, ec); break;
|
||||
case command::smembers: adapter::get<std::set<mystruct>>(adapters_)(nd, ec); break;
|
||||
case command::hgetall: adapter::get<std::map<std::string, mystruct>>(adapters_)(nd, ec); break;
|
||||
case command::get: adapter0_(nd, ec); break;
|
||||
case command::lrange: adapter1_(nd, ec); break;
|
||||
case command::smembers: adapter2_(nd, ec); break;
|
||||
case command::hgetall: adapter3_(nd, ec); break;
|
||||
default:; // Ignore
|
||||
}
|
||||
}
|
||||
@@ -122,33 +122,33 @@ public:
|
||||
|
||||
case command::get:
|
||||
{
|
||||
if (std::get<boost::optional<mystruct>>(resps_).has_value()) {
|
||||
std::cout << std::get<boost::optional<mystruct>>(resps_).value() << "\n\n";
|
||||
std::get<boost::optional<mystruct>>(resps_).reset();
|
||||
if (resp0_.has_value()) {
|
||||
std::cout << resp0_.value() << "\n\n";
|
||||
resp0_.reset();
|
||||
} else {
|
||||
std::cout << "Expired." << "\n";
|
||||
}
|
||||
} break;
|
||||
|
||||
case command::lrange:
|
||||
for (auto const& e: std::get<std::list<mystruct>>(resps_))
|
||||
for (auto const& e: resp1_)
|
||||
std::cout << e << "\n";
|
||||
std::cout << "\n";
|
||||
std::get<std::list<mystruct>>(resps_).clear();
|
||||
resp1_.clear();
|
||||
break;
|
||||
|
||||
case command::smembers:
|
||||
for (auto const& e: std::get<std::set<mystruct>>(resps_))
|
||||
for (auto const& e: resp2_)
|
||||
std::cout << e << "\n";
|
||||
std::cout << "\n";
|
||||
std::get<std::set<mystruct>>(resps_).clear();
|
||||
resp2_.clear();
|
||||
break;
|
||||
|
||||
case command::hgetall:
|
||||
for (auto const& e: std::get<std::map<std::string, mystruct>>(resps_))
|
||||
for (auto const& e: resp3_)
|
||||
std::cout << e.first << ", " << e.second << std::endl;
|
||||
std::cout << "\n";
|
||||
std::get<std::map<std::string, mystruct>>(resps_).clear();
|
||||
resp3_.clear();
|
||||
break;
|
||||
|
||||
default:;
|
||||
@@ -163,8 +163,16 @@ public:
|
||||
void on_push() { }
|
||||
|
||||
private:
|
||||
responses_tuple_type resps_;
|
||||
adapters_tuple_type adapters_;
|
||||
T0 resp0_;
|
||||
T1 resp1_;
|
||||
T2 resp2_;
|
||||
T3 resp3_;
|
||||
|
||||
adapter_t<T0> adapter0_;
|
||||
adapter_t<T1> adapter1_;
|
||||
adapter_t<T2> adapter2_;
|
||||
adapter_t<T3> adapter3_;
|
||||
|
||||
client_type* db_;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,19 +15,16 @@
|
||||
namespace net = boost::asio;
|
||||
namespace adapter = aedis::adapter;
|
||||
using aedis::resp3::node;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapter_t;
|
||||
using aedis::redis::command;
|
||||
using aedis::generic::client;
|
||||
using aedis::adapter::adapt;
|
||||
using aedis::adapter::adapters_tuple_t;
|
||||
using aedis::adapter::make_adapters_tuple;
|
||||
|
||||
// Responses used in the example.
|
||||
using T0 = std::list<int>;
|
||||
using T1 = boost::optional<std::set<std::string>>;
|
||||
|
||||
using client_type = client<net::ip::tcp::socket, command>;
|
||||
using responses_tuple_type =
|
||||
std::tuple<
|
||||
std::list<int>,
|
||||
boost::optional<std::set<std::string>>,
|
||||
std::vector<node<std::string>>
|
||||
>;
|
||||
using adapters_tuple_type = adapters_tuple_t<responses_tuple_type>;
|
||||
|
||||
template <class Container>
|
||||
void print_and_clear(Container& cont)
|
||||
@@ -38,10 +35,11 @@ void print_and_clear(Container& cont)
|
||||
cont.clear();
|
||||
}
|
||||
|
||||
class myreceiver {
|
||||
class receiver {
|
||||
public:
|
||||
myreceiver(client_type& db)
|
||||
: adapters_(make_adapters_tuple(resps_))
|
||||
receiver(client_type& db)
|
||||
: adapter0_(adapt(resp0_))
|
||||
, adapter1_(adapt(resp1_))
|
||||
, db_{&db} {}
|
||||
|
||||
void on_connect()
|
||||
@@ -56,8 +54,8 @@ public:
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
switch (cmd) {
|
||||
case command::lrange: adapter::get<std::list<int>>(adapters_)(nd, ec); break;
|
||||
case command::smembers: adapter::get<boost::optional<std::set<std::string>>>(adapters_)(nd, ec); break;
|
||||
case command::lrange: adapter0_(nd, ec); break;
|
||||
case command::smembers: adapter1_(nd, ec); break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
@@ -92,11 +90,11 @@ public:
|
||||
} break;
|
||||
|
||||
case command::lrange:
|
||||
print_and_clear(std::get<std::list<int>>(resps_));
|
||||
print_and_clear(resp0_);
|
||||
break;
|
||||
|
||||
case command::smembers:
|
||||
print_and_clear(std::get<boost::optional<std::set<std::string>>>(resps_).value());
|
||||
print_and_clear(resp1_.value());
|
||||
break;
|
||||
|
||||
default:;
|
||||
@@ -111,8 +109,14 @@ public:
|
||||
void on_push() { }
|
||||
|
||||
private:
|
||||
responses_tuple_type resps_;
|
||||
adapters_tuple_type adapters_;
|
||||
// Responses
|
||||
T0 resp0_;
|
||||
T1 resp1_;
|
||||
|
||||
// Adapters.
|
||||
adapter_t<T0> adapter0_;
|
||||
adapter_t<T1> adapter1_;
|
||||
|
||||
client_type* db_;
|
||||
};
|
||||
|
||||
@@ -120,7 +124,7 @@ int main()
|
||||
{
|
||||
net::io_context ioc;
|
||||
client_type db{ioc.get_executor()};
|
||||
myreceiver recv{db};
|
||||
receiver recv{db};
|
||||
|
||||
db.async_run(
|
||||
recv,
|
||||
|
||||
@@ -41,22 +41,23 @@ int main()
|
||||
net::connect(socket, res);
|
||||
|
||||
// Creates and sends a request to redis.
|
||||
std::string request;
|
||||
auto sr = make_serializer(request);
|
||||
std::string buffer;
|
||||
auto sr = make_serializer(buffer);
|
||||
sr.push(command::hello, 3);
|
||||
sr.push(command::ping);
|
||||
sr.push(command::quit);
|
||||
net::write(socket, net::buffer(request));
|
||||
net::write(socket, net::buffer(buffer));
|
||||
buffer.clear();
|
||||
|
||||
// Responses
|
||||
std::string resp;
|
||||
hello_type hello;
|
||||
|
||||
// Reads the responses to all commands in the request.
|
||||
std::string buffer;
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt(hello)); // hello
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt(resp));
|
||||
resp3::read(socket, dynamic_buffer(buffer)); // quit (ignored)
|
||||
auto dbuffer = dynamic_buffer(buffer);
|
||||
resp3::read(socket, dbuffer, adapt(hello));
|
||||
resp3::read(socket, dbuffer, adapt(resp));
|
||||
resp3::read(socket, dbuffer);
|
||||
|
||||
std::cout << std::get<0>(hello) << ": " << std::get<1>(hello) << std::endl;
|
||||
std::cout << "Ping: " << resp << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user