Как правильно асинхронно читать SslStream по частям?
Доброго времени суток!
На сервере в бесконечном цикле я читаю данные от клиента при помощи метода ReadAsync класса SslStream приблизительно следующим образом:
// client_stream - экземпляр SslStream.
while (true) {
// MemoryStream received_stream = ... // Поток принятых данных.
byte[] buffer = new byte[64];
int bytes_read = 0;
do {
bytes_read = await client_stream.ReadAsync(buffer, 0, buffer.Length, /* токен отмены */);
// Добавляем данные в поток принятых данных received_stream.
}
while (bytes_read > 0);
// Обрабатываем данные в потоке received_stream.
}
Что я пытаюсь сделать в этом алгоритме? Я по частям размером с длину buffer принимаю данные от клиента и записываю их в поток принятых данных, который по итогу будет заключать в себе обращение клиента к серверу, на которое клиент ожидает ответа. Вы могли заметить комментарий в конце "обрабатываем данные". А принятые данные то не обрабатываются своевременно.
Проблема заключается в том, что вызов ... = await client_stream.ReadAsync(...);, как бы нелепо это ни звучало, блокирует выполнение потока. Первая итерация цикла do .. while: поток ждет данных, и это правильно. Допустим, он принял 2 байта. Выполнение продолжилось. Принятые байты добавлены в поток принятых данных. Количество принятых байт больше нуля. Переходим ко второй итерации цикла do .. while. Как Хатико ждем данных от клиента и получаем исключение. Что произошло? Клиент не дождался ответа на обращение и сбросил соединение с сервером. Браво! Алгоритм ничтожен.
В документации сказано, что SslStream.ReadAsync возвращает 0, когда больше нет данных для чтения, но на практике это приносит только головную боль: да, он возвращает 0 и не блокирует выполнение потока после вызова WriteAsync. Но если WriteAsync не вызывался, то он просто блокирует поток до получения данных от клиента. Лог переполнен, алгоритм не работает. Шикарно!
Я также не могу проверить количество доступных байт для чтения (в самом SslStream, а не сокете) для остановки цикла do .. while. Я не могу удостовериться в том, что я в конце потока SslStream. Это заводит меня в тупик и я уже долго не могу исправить алгоритм.
Вопрос: как мне исправить или реализовать алгоритм принятия (большого количества) данных от клиента по частям при том, что данные после получения должны быть обработаны как можно скорее (необходимо ответить клиенту или клиент разорвет соединение).