Может ли один экземпляр std::io::BufReader
на tokio::net::TcpStream
привести к потере данных, когда BufReader
используется для read_until
aзаданный (байтовый) разделитель?
То есть есть ли вероятность, что после того, как я использую BufReader
для:
let buffer = Vec::new();
let reader = BufReader::new(tcp_stream);
tokio::io::read_until(reader, delimiter, buffer)
.map(move |(s, _)| s.into_inner())
, последующее tokio::io::read
с использованием того же потока вернет данныечто на самом деле выходит за разделитель + 1, вызывая, таким образом, потерю данных?
У меня есть проблема (и полный воспроизводимый пример в Linux ), которую я не могу объяснить, если приведенное выше предположениене правильно
У меня есть сервер TCP, который должен отправлять содержимое файла нескольким клиентам TCP после нескольких одновременных запросов.
Иногда, используя всегда одни и те же входные данные, данные, полученные клиентомменьше ожидаемого, поэтому передача не удалась.
Ошибка не возникает в 100% случаев (то есть некоторые запросы клиентов все еще выполняются), но при 100 попытках, определенных в tcp_client.rs
, этовсегда можно было воспроизвести хотя бы для одного из них.
Последовательность данных, передаваемых между клиентом и сервером, состоит из:
- , клиент отправляет запрос
- сервер прочитал запрос и отправил ответ
- клиент прочитал ответ
- сервер отправил файл данных
- клиент прочитал файл данных
Эта проблема воспроизводима только в том случае, если задействованы шаги 1, 2 и 3, в противном случае она работает как положено.
Ошибка возникает, когда это tokio::io::read
(используется для чтениясодержимое файла) возвращает 0, как если бы сервер закрыл соединение, даже если сервер действительно запущен и работает, и все данные были отправлены (после tokio::io::copy
есть подтверждение, и я проверилпакеты TCP, использующие анализатор пакетов). Кстати, во всех моих прогонах количество данных, прочитанных до ошибки, всегда было> 95%, чем ожидалось.
Самое главное, модуль common.rs
определяет 2 различные функции read_*
:
Логика2 - то же самое, они должны прочитать запрос / ответ (и клиент и сервер могут быть обновлены, чтобы использовать один или другой). Что удивительно, так это то, что ошибка появляется только при использовании tokio::io::read_until
, тогда как tokio::io::read_exact
работает, как и ожидалось.
Если только я не использовал tokio::io::read_until
или в моей реализации есть ошибка, я ожидал, что обаверсии для работы без каких-либо проблем. Вместо этого я вижу эту панику , вызванную тем, что некоторые клиенты не могут прочитать все данные, отправленные сервером.