-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient-sink.cpp
More file actions
112 lines (92 loc) · 3.59 KB
/
client-sink.cpp
File metadata and controls
112 lines (92 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// This example demonstrates how to implement a TCP client which acts as a data sink. It
// connects to a streaming server, then subscribes to the signal "/Value", and prints messages to
// the console when data packets are received. The "server-source" sample provides a suitable
// server for this demo to connect to. Press Ctrl+C to gracefully shut down the client.
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <boost/asio.hpp>
#include <ws-streaming/ws-streaming.hpp>
using namespace std::placeholders;
void on_disconnected(
std::shared_ptr<boost::asio::signal_set> signal_handler,
const boost::signals2::connection& slot_connection,
const boost::system::error_code& ec)
{
slot_connection.disconnect();
std::cout << "connection closed (error code: " << ec << ')' << std::endl;
}
void on_data_received(
std::int64_t domain_value,
std::size_t sample_count,
const void *data,
std::size_t size)
{
std::cout << "received " << size << " data byte(s), " << sample_count << " sample(s) with domain value " << domain_value << std::endl;
}
void on_available(std::string target_signal_id, wss::remote_signal_ptr signal)
{
std::cout << "available signal: " << signal->id() << std::endl;
// Subscribe to the signal with ID "/Value".
if (signal->id() == target_signal_id)
{
signal->on_data_received.connect(on_data_received);
signal->subscribe();
}
}
void on_unavailable(wss::remote_signal_ptr signal)
{
std::cout << "signal no longer available: " << signal->id() << std::endl;
}
void on_connected(
std::string target_signal_id,
const boost::system::error_code& ec,
wss::connection_ptr connection)
{
if (ec)
{
std::cerr << "connection failed: " << ec << std::endl;
return;
}
std::cout << "connected to server" << std::endl;
// Set up a signal handler to stop the connection attempt when Ctrl+C is pressed.
auto signal_handler = std::make_shared<boost::asio::signal_set>(connection->executor(), SIGINT);
signal_handler->async_wait([connection](const boost::system::error_code& ec, int signal)
{
if (!ec)
connection->close();
});
// We wish to keep the Ctrl+C signal handler active until the connection is closed. To do
// this, we store a shared_ptr for it in the Boost.Signals2 slot connection for
// on_disconnected, which, when called, will disconnect itself and thereby destroy the signal
// handler.
connection->on_disconnected.connect_extended(
decltype(connection->on_disconnected)::extended_slot_type{
&on_disconnected,
signal_handler,
_1,
_2});
// Call on_available when any signal becomes available from the server.
connection->on_available.connect(std::bind(on_available, target_signal_id, _1));
connection->on_unavailable.connect(on_unavailable);
}
int main(int argc, char *argv[])
{
// Allow the URL to be specified as the first argument.
std::string url = "ws://localhost:7414";
if (argc >= 2)
url = argv[1];
// Allow the signal name to be specified as the second argument.
std::string target_signal_id = "/Value";
if (argc >= 3)
target_signal_id = argv[2];
// Set up a single-threaded Boost.Asio execution context.
boost::asio::io_context ioc{1};
// Try to connect to the server; on_connected() will be called on success/failure.
wss::client client{ioc.get_executor()};
client.async_connect(url, std::bind(on_connected, target_signal_id, _1, _2));
ioc.run();
}