Есть ли альтернатива System.IO.BufferedStream в C#?
Я получаю следующее исключение:
System.NotSupportedException : This stream does not support seek operations.
at System.Net.Sockets.NetworkStream.Seek(Int64 offset, SeekOrigin origin)
at System.IO.BufferedStream.FlushRead()
at System.IO.BufferedStream.WriteByte(Byte value)
Следующая ссылка показывает, что это известная проблема для Microsoft. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=273186
Эта трассировка стека показывает 2 вещи:
- System.IO.BufferedStream выполняет некоторую абсурдную операцию перемещения указателя. BufferedStream должен буферизовать основной поток и не более. Качество буфера будет плохим, если будет такая операция поиска.
- Он никогда не будет работать стабильно с потоком, который не поддерживает Seek.
Есть ли альтернативы? Нужен ли мне буфер вместе с NetworkStream в C# или это уже буферизовано?
Редактировать: я хочу просто уменьшить количество вызовов чтения / записи в основной поток сокета.
3 ответа
NetworkStream уже буферизован. Все полученные данные хранятся в буфере, ожидая, пока вы их прочитаете. Вызовы для чтения будут либо очень быстрыми, либо заблокируют ожидание получения данных от другого узла в сети, BufferedStream не поможет в любом случае.
Если вас беспокоит блокировка, вы можете посмотреть, как переключить основной сокет в неблокирующий режим.
BufferedStream
просто действует, чтобы уменьшить количество вызовов чтения / записи к базовому потоку (который может быть связан с IO/ аппаратным обеспечением). Он не может обеспечить возможность поиска (и, действительно, буферизация и поиск во многом противоречат друг другу).
Зачем тебе искать? Возможно, сначала скопируйте поток на что-то доступное для поиска. MemoryStream
или FileStream
- затем сделайте свою настоящую работу из этого второго, доступного для поиска потока.
Вы имеете в виду конкретную цель? Я могу предложить более подходящие варианты с более подробной информацией...
В частности: обратите внимание, что NetworkStream
это любопытство - с большинством потоков чтение / запись относятся к одному и тому же физическому потоку; однако, NetworkStream
фактически представляет собой две совершенно независимые трубы; чтение и запись совершенно не связаны. Кроме того, вы не можете искать в байтах, которые уже прошли мимо вас... вы можете пропустить данные, но это лучше сделать, выполнив несколько Read
изменения и отбрасывание данных.
Решение состоит в том, чтобы использовать два независимых BufferedStream
s, один для получения и один для отправки. И не забудьте очистить отправку BufferedStream
соответственно.
Поскольку даже в 2018 году, кажется, трудно получить удовлетворительный ответ на этот вопрос, ради человечества, вот мои два цента:
NetworkStream
буферизируется на стороне ОС. Однако это не означает, что нет причин для буферизации на стороне.net. TCP работает хорошо при записи-чтении (повтор), но останавливается при записи-записи-чтении из-за задержки подтверждения и т. Д. И т. Д.
Если у вас, как и у меня, есть куча протокольного кода, который можно взять в двадцать первом веке, вы можете создать буфер.
В качестве альтернативы, если вы придерживаетесь вышеизложенного, вы также можете буферизовать только чтение /rcvs или только запись / отправку, и использоватьNetworkStream
непосредственно для другой стороны, в зависимости от того, какой код нарушен.Вы просто должны быть последовательными!
КакиеBufferedStream
Документы не дают полной ясности в том, что вам следуетпереключать чтение и запись только в том случае, если ваш поток доступен для поиска. Это потому, что он буферизует чтение и запись в одном и том же буфере. BufferedStream
просто не работает хорошо дляNetworkStream
,
Как отметил Марк, причиной этой хромоты является слияние двух потоков в один NetworkStream, что не является одним из величайших проектных решений.net.