Я бы сказал, что это не имеет большого значения. Чтобы напрямую ответить на вопрос, вот что делается для реализации реактивных сокетов (например, Linux), предварительно обработанных и переформатированных:
size_t available(socket_type s, boost::system::error_code& ec) {
if (s == invalid_socket) {
ec = boost::asio::error::bad_descriptor;
return 0;
}
ioctl_arg_type value = 0;
int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec);
if (result == 0)
ec = boost::system::error_code();
return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);
}
Как видите, все это должно быть встроено в прямой FIONREAD
ioctl
, исключая условия ошибки. Это довольно скудно и не займет меньше времени, если вы сделаете это напрямую, на случай, если вы захотите проверить:
static inline size_t my_available(boost::asio::ip::tcp::socket& socket, boost::system::error_code& ec) {
auto s = socket.native_handle();
if (s == -1) {
ec = boost::asio::error::bad_descriptor;
return 0;
}
int value = 0;
if (auto err = ::ioctl(s, FIONREAD, &value))
ec = boost::system::error_code(err, boost::asio::error::get_system_category());
else
ec = boost::system::error_code();
return ec? value : 0;
}
Если хотите чтобы дождаться, пока данные станут доступны и действовать при первой возможности, тогда вы можете async_wait
на сокете: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio/reference/basic_stream_socket/async_wait.html
Вы можете указать ожидание доступности чтения / записи, или при наличии состояния ожидающей ошибки
Документы: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio/overview/core/reactor.html