Получение пакета данных NetworkStream C#
Есть проблема в получении данных по TCP/IP. При соединении Хост отправляет данные размером 32 байта один раз в 500мс, в нем организован так же буфер, который при проблемах со связью накапливается и при появлении оной, начинает снова отправлять пакеты по сети. Для их получения я использую на клиенте TcpClient и NetworkStream. Я написал следующий код:
public byte[] ReadData()
{
var receivedData = new byte[BufferSize];
try
{
tcpClient.ReceiveTimeout = ReceiveTimeout;
var stream = tcpClient.GetStream();
var receivedBytes = stream.Read(receivedData, 0, receivedData.Length);
return receivedData;
}
catch (Exception e)
{
_logger.ErrorMessage("Ошибка чтения: ", e);
}
throw new ApplicationException("Ошибка чтения или подключения к хосту!");
}
Использование:
while (!cancelToken.IsCancellationRequested)
{
var data = client.ReadData();
_dbContext.Save(Guid.NewGuid, data);
}
В управляющем коде, после открытия хоста в бесконечном цикле вызывается данный метод. Все работает прекрасно, пока не происходят проблемы с сетью. Из-за того что на хосте есть накапливаемый буфер, после возобновления связи он начинает выплевывать данные, но теряется последовательность пакета. Как правильно обработать и накопить "правильные" 32 байта данных? В них нет никаких сплиттеров, разграничителей и банальных старт-стоп байт. В теории, читать бы это все по байтово (может binary reader и складывать в массив каждый байт?) и как только размер будет 32 - считаем, что пакет пришел правильный. UPDATE 15.06.2021 Измененный метод, с добавлением метода из ответа @VladD
public void ReadData()
{
do
{
try
{
tcpClient.ReceiveTimeout = 500;
var stream = tcpClient.GetStream();
var receivedBytes = BitConverter.ToInt32(ReadExact(stream, ReceivedBufferSize), 0);
var receivedData = ReadExact(stream, receivedBytes); // Отсюда уже не выходит....
ReceivedDataEvent?.Invoke(new DataReceivedEventArgs(receivedData));
}
catch (Exception e)
{
_logger.ErrorMessage("Ошибка чтения: ", e);
CloseConnection();
}
} while (!cancelToken.IsCancellationRequested);
}