Я работаю с boost::asio
за TCP
общение между клиентом & Серверное приложение, оба из которых написаны мной. Я изначально написал это с синхронным чтением данных, которое использует boost::asio::read
, sync_read
работает все хорошо, за исключением того, что я не могу так сделать socket.cancel
во время операции чтения. Это стало довольно сдерживающим фактором & следовательно Я сейчас пытаюсь преобразовать мое синхронное чтение, чтобы сделать async_read
механизм.
Ниже был мой механизм синхронного чтения, который действительно хорошо. Я делаю 2 чтения. Сначала получите заголовок пакета, затем получите данные пакета, которые работают довольно хорошо ->
size_t Read_Data_Sync(std::vector<unsigned char> & msg_body) {
//fetch the header
MyMessageHeader msg_header;
boost::system::error_code err_code;
size_t bytes_received = boost::asio::read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), err_code);
if (bytes_received <= 0 || err_code)
return 0;
err_code.clear();
msg_body.resize(msg_header.size);
//fetch the body
bytes_received = boost::asio::read(socket, boost::asio::buffer(msg_body), err_code);
if (bytes_received <= 0 || error_code)
return 0;
return bytes_received;
}
Выше функция используется для непрерывного вызова из thread
на стороне клиента, который я называю потоком читателя like so
->
auto data_reader_thread = std::thread {[this] {
while(run_thread) {
Read_Data_Sync();
}
}};
Вот как я изменяю это, чтобы сделать механизм чтения async
->
Поток чтения остается таким же, за исключением того, что теперь он вызывает другую функцию чтения, которую я кодировал для чтения данных в async
путь
auto data_reader_thread = std::thread {[this] {
while(run_thread) {
Read_Data_Async();
}
}};
Я сделал msg_body
& msg_header
как переменные-члены в моем классе. Обновленная логика такова, что Read_Data_Async
вызывается из функции потока непрерывно. Read_Data_Async
звонки boost::asio::async_read
переплет
адрес Handle_Read_Header
в качестве обратного вызова, который в свою очередь снова делает boost::asio::async_read
читать тело сообщения, передавая обработчик обратного вызова для получения message_body
void Read_Data_Async()
{
//firstly read message header
MyMessageHeader msg_header;
boost::asio::async_read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), boost::bind(&TCPSession::Handle_Read_Header, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void Handle_Read_Header(const boost::system::error_code & error, std::size_t bytes_transferred)
{
//now read the message body
if (!error && bytes_transferred > 0) {
boost::asio::async_read(socket, boost::asio::buffer(msg_body), boost::bind(&TCPSession::Handle_Read_Body, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else {
cout << "Error: " << error << "\n";
}
}void Handle_Read_Body(const boost::system::error_code & error, std::size_t bytes_transferred)
{
if (!error && bytes_transferred > 0) {
// msg_body has the data read from socket
}
else if (error != boost::asio::error::eof) {
cout << "Error: " << error << "\n";
}
}
Проблема, с которой я сталкиваюсь сейчас, заключается в том, что обратный вызов Handle_Read_Header
никогда не перезвонят !! Что не так с тем, что я делаю? Я просмотрел довольно много похожих постов, таких как этот пытаясь решить мой
проблема, но опять же, что ссылка предлагает позвонить io.run
потому что о boost::asio::async_read_until
не boost::asio::async_read
,
Правильна ли моя приведенная выше логика по отношению к boost::asio::async_read
? Что я должен получить asio
перезвонить моей функции обработчика?
Ты должен бежать io_service::run()
где-то ¹
На самом деле, вся идея асинхронного ввода-вывода заключается в том, что вы делаете НЕ нужны отдельные потоки для чтения / записи: полный дуплекс полностью возможен в одном потоке.
¹ или более сложный цикл с run_one, poll или poll_one
Других решений пока нет …