У меня есть это требование, когда мое приложение должно подключаться к другому приложению через сокеты и должно поддерживать постоянное соединение в течение долгого времени. Мое приложение будет TCP-клиентом, а другое - TCP-сервером. Мое приложение отправит команды, и сервер ответит соответственно.
Проблема, с которой я сейчас сталкиваюсь, заключается в том, как прочитать все данные с сервера в строку и вернуть приложение, которое выдаст следующую команду. Синхронное чтение (с asio::read
) выглядело как хороший вариант до тех пор, пока я не заметил зависание сокета, пока я не завершил работу сервера. Просматривая документацию, я обнаружил, что библиотека работает правильно.
его функция используется для чтения определенного количества байтов данных из потока. Вызов будет блокироваться до тех пор, пока не будет выполнено одно из следующих условий:
1. Поставленные буферы заполнены. То есть переданные байты равны сумме размеров буфера.
2. Произошла ошибка.
Проблема в том, что я не знаю правильный размер буфера, так как ответ от сервера меняется. Так что, если я поставлю слишком маленький буфер, он вернется нормально, но пропустит некоторые данные. Если я поставлю слишком большой, он будет зависать вечно, пока сервер не выйдет.
Так что я подумал, что буду делать асинхронное чтение. Он работает только один раз, и я не знаю, как заставить его извлекать данные, пока все данные не будут прочитаны.
вот соответствующий асинхронный код
#define ASIO_STANDALONE 1
#include <iostream>
#include <asio.hpp>
int main()
{
asio::io_context context;
size_t reply_length;
size_t length = 1024;
std::vector<char> buffer;
//create socket
asio::ip::tcp::socket socket(context);
socket.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), 8088));
std::string dataOut = "list --files"; //some command to write
std::error_code error;
asio::write(socket, asio::buffer(dataOut), error);
if (!error)
{
std::cout << "Receiving...!" << std::endl;
buffer.resize(length);
asio::async_read(socket, asio::buffer(buffer), [&buffer, &context](const asio::error_code &ec, std::size_t bytes_transferred) {
std::copy(buffer.begin(), buffer.end(), std::ostream_iterator<char>(std::cout, ""));
std::cout << "\nRead total of:" << bytes_transferred << "\n";
context.run();
});
}
else
{
std::cout << "send failed: " << error.message() << std::endl;
}
context.run();
}
Поиск не помог мне решить мою проблему.
Итак, мой вопрос: как я могу прочитать все данные в постоянном сокете с asio? Не использую повышение.