I have a remote server that constantly sends a message like this to my pc:
{Heartbeat}
Furthermore, the remote server listens to my command messages that I send from my pc connected to the remote server, using a string in json format, for example:
{'H': '1', 'N': 3, 'D1': 3, 'D2': 150}
The remote server then sends me the response like, for example:
{1:ok}
Sometimes, however, it happens that the answer is drowned out by the various heartbeats, for example:
{Heartbeat}{Heartbeat}{Heartbeat}{1:ok}{Heartbeat}{Heartbeat}
How can I filter this long sequence {...} extracting only the useful information {1:ok} using C++17 ? As library for TCP/IP communication I use boost ASIO 1.81.0.
For TCP/IP communication in C++17 I make use of a TCPClient class. In main I send this command to the server:
client->Send_cmd("{\'H\': \'1\', \'N\': 3, \'D1\': 3, \'D2\': 150}");
As seen in the TCPClient class I use as a member function to send a message to the server, the following:
void TCPClient::Send_cmd(std::string data)
{
// search for substring
std::string ricerca = "";
std::string response = "";
std::string response_tmp = "";
std::string::iterator i1; // Declaration of an iterator to store the returned pointer
boost::system::error_code error;
// result indicates the number of data bytes transmitted
auto result = boost::asio::write(*m_socket, boost::asio::buffer(data), error);
if (!error) {
esito_cmd_al_server = "Client sent the command";
}
else {
esito_cmd_al_server = "send failed: " + error.message();
}
// We just have to read the response from the server
for (;;)
{
// We use a boost::array to hold the received data.
// Instead of a boost::array, we could have used a char [] or std::vector.
//boost::array<char, 128> buf;
boost::asio::streambuf buf2;
boost::system::error_code error;
// The boost::asio::buffer() function automatically determines the size
// of the array to help prevent buffer overflow.
//size_t len = m_socket->read_some(boost::asio::buffer(buf), error);
size_t len2 = boost::asio::read_until(*m_socket, buf2, "}");
// for correctness I keep the response on the first {...} and if there are other {...} I delete them
ricerca = "}";
response = boost::asio::buffer_cast<const char*>(buf2.data());
// look for the first occurrence of "}"
i1 = std::search(response.begin(), response.end(), ricerca.begin(), ricerca.end());
// if it encountered "}", then delete the rest of the response
if (i1 != response.end())
{
std::string finale2 = response.substr(0, (i1 - response.begin()) + 1);
response = finale2;
}
// check that the incoming message from the server-robot is not a "{Heartbeat}"
std::string search = "{Hea";
i1 = std::search(response.begin(), response.end(), search.begin(), search.end());
// if it encountered "{Heartbeat}", then repeat the for loop
if (i1 != response.end())
{
response = "";
continue;
}
response_tmp = response;
// When the server closes the connection, the function boost::asio::ip::tcp::socket::read_some()
// will exit with error boost::asio::error::eof
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
//std::string tmp_str(buf.data(), len);
//std::string tmp_str2 = boost::asio::buffer_cast<const char*>(buf2.data());
//esito_cmd_al_server = tmp_str2;
esito_cmd_al_server = response_tmp;
if ("{Heartbeat}" == esito_cmd_al_server)
continue;
else
break;
}
}
Is there a more correct way (mine seems a bit cumbersome) to carry out the filtering I wrote ?