Выход без буфера из IHTTPHandler


Я хочу передавать данные из класса IHttpHandler. Я загружаю большое количество строк из базы данных, сериализую и сжимаю их, а затем отправляю их по проводу. С другой стороны, я хочу, чтобы мой клиент мог распаковать и десериализовать данные до того, как сервер завершит сериализацию всех объектов.

Я использую context.Response.OutputSteam.Write для записи своих данных, но все равно кажется, что выходные данные помещаются в буфер перед отправкой клиенту. Есть ли способ избежать этого буферизация?

2 3

2 ответа:

Метод Response.Flush должен отправить его по проводу; однако есть некоторые исключения. Если IIS использует динамическое сжатие, то есть он настроен на сжатие динамического содержимого, то IIS не будет сбрасывать поток. Затем идет целая "разрозненная" кодировка передачи. Если вы не указали Content-Length, то принимающий конец не знает, насколько большим будет тело ответа. Это достигается с помощью фрагментированного кодирования передачи. Некоторые HTTP-серверы требуют, чтобы клиент использовал Accept-Encoding заголовок запроса, содержащий ключевое слово chunked. Другие просто по умолчанию разделяются, когда вы начинаете писать байты до указания полной длины; однако они не делают этого, если вы указали свой собственный заголовок ответа Transfer-Encoding.

С IIS 7 и отключенным сжатием, Response.Flush должен всегда делать трюк, верно? Не совсем. IIS 7 может иметь много модулей, которые перехватывают и взаимодействуют с запросом и ответом. Я не знаю, установлены ли они/включены по умолчанию, но вы должны но все же имейте в виду, что они могут повлиять на ваш желаемый результат.

... Я загружаю большое количество строк из БД, сериализую и сжатие их, а затем отправить их вниз по проводу...

Любопытно, что вы сжимаете это содержание. Если вы используете GZIP, то вы не будете контролировать, когда и сколько данных отправляется при вызове flush. Кроме того, использование содержимого GZIP означает, что принимающая сторона также может быть не в состоянии начать чтение данных сразу. Вы можете разбить записи на более мелкие, удобоваримые блоки по 10, 50 или 100 строк. Сожмите его и отправьте, а затем работайте над следующим набором строк. Конечно, теперь вам нужно будет написать что-то клиенту, чтобы он знал, насколько велик каждый сжатый набор строк, и когда они дойдут до конца. см. http://en.wikipedia.org/wiki/Chunked_transfer_encoding для примера того, как работает фрагментированная передача.

Вы можете использовать context.Response.Flush() или context.Response.OutputSteam.Flush(), чтобы заставить буферизованное содержимое быть записанным немедленно.