I am trying to asynchronously send and receive custom data packets with boost and I have some questions, based on my current implementation:
tcpclient.cpp
#include "tcpclient.h"
#include <boost/chrono.hpp>
#include "../utils/logger.h"
tcpclient::tcpclient(std::string host, int port) :
_endpoint(boost::asio::ip::address::from_string(host), port), _socket(_ioservice) {
logger::log_info("Initiating client ...");
}
void tcpclient::start() {
connect();
_ioservice.run();
}
void tcpclient::connect() {
_socket.async_connect(_endpoint, std::bind(&tcpclient::connect_handler, this, std::placeholders::_1));
}
void tcpclient::receive() {
boost::asio::async_read(_socket, boost::asio::buffer(data, HEADER_LEN), std::bind(&tcpclient::read_handler, this, std::placeholders::_1));
}
void tcpclient::connect_handler(const boost::system::error_code &error) {
if (!error) {
_status = CONNECTED;
logger::log_info("Connected to " + get_remote_address_string());
receive();
} else {
_status = NOT_CONNECTED;
_socket.close();
_timer.expires_from_now(boost::asio::chrono::seconds{2});
_timer.async_wait(std::bind(&tcpclient::reconnect_handler, this, std::placeholders::_1));
logger::log_info("Failed to connect");
}
}
void tcpclient::reconnect_handler(const boost::system::error_code &error) {
connect();
}
void tcpclient::read_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
logger::log_info("reading some data?");
}
std::string tcpclient::get_remote_address_string() {
return _socket.remote_endpoint().address().to_string() + ":" + std::to_string(_socket.remote_endpoint().port());
}
tcpclient.h
#include <string>
#include <boost/asio.hpp>
enum ConnectionStatus{
NOT_CONNECTED,
CONNECTED
};
class tcpclient {
public:
tcpclient(std::string host, int port);
void start();
void connect();
private:
ConnectionStatus _status = NOT_CONNECTED;
const int HEADER_LEN = 0x01;
void receive();
void connect_handler(const boost::system::error_code& error);
void reconnect_handler(const boost::system::error_code &error);
void read_handler(const boost::system::error_code& error);
std::string get_remote_address_string();
boost::asio::io_service _ioservice;
boost::asio::ip::tcp::endpoint _endpoint;
boost::asio::ip::tcp::socket _socket;
boost::asio::steady_timer _timer{_ioservice, boost::asio::chrono::seconds{2}};
};
1) Would it make sense to add two seperate handlers for reading and writing, one for the header one for the body?
2) How can I ensure that I can send and receive data at the same time without running into any issues? Does this require multiple sockets? How is such functionality usually implemented?
3) How would I go sending custom data structures? I want to implement a custom packet structure. How would I sent such objects, does boost have an inbuilt serializer? How or custom data structures sent and received?
4) What happens if the connection drops during sending or receiving data? Are such exceptions handled directly in the receive/send handlers by checking the errorcode object for eof?
A basic example for that would help a lot!