Я пытаюсь асинхронно отправлять и получать пользовательские пакеты данных с надстройкой, и у меня есть несколько вопросов, основанных на моей текущей реализации:
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) Имеет ли смысл добавить два отдельных обработчика для чтения и записи, один для заголовка, другой для тела?
2) Как я могу гарантировать, что могу отправлять и получать данные одновременно, не сталкиваясь с какими-либо проблемами? Требуется ли для этого несколько сокетов? Как обычно реализуется такая функциональность?
3) Как мне отправлять пользовательские структуры данных? Я хочу реализовать собственную структуру пакетов. Как бы я отправил такие объекты, есть ли у boost встроенный сериализатор? Как или пользовательские структуры данных отправлены и получены?
4) Что произойдет, если соединение разорвется во время отправки или получения данных? Обрабатываются ли такие исключения непосредственно в обработчиках приема / отправки путем проверки объекта errorcode на eof?
Базовый пример для этого очень поможет!