Здесь есть несколько факторов. Чтобы устранить несколько проблем, Apache и bash не буферизуют какой-либо вывод. Вы можете проверить с помощью этого сценария:
#!/bin/sh
cat <<END
Content-Type: text/plain
END
for i in $(seq 1 10)
do
echo $i
sleep 1
done
Стик это где-то, что Apache настроен на выполнение CGI-скриптов, и тест с Netcat:
$ nc localhost 80
GET /cgi-bin/chunkit.cgi HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Date: Tue, 24 Aug 2010 23:26:24 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.7l DAV/2
Transfer-Encoding: chunked
Content-Type: text/plain
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
10
0
Когда я делаю это, я вижу в Netcat каждое число, фигурирующее раз в секунду, как и предполагалось.
Обратите внимание, что моя версия Apache, по крайней мере, автоматически применяет кодировку с передачей пакетов, предположительно потому, что я не включил Content-Length
; если вы сами возвращаете заголовок Transfer-Encoding: chunked
, тогда вам нужно закодировать вывод вашего скрипта в кодировке с кодировкой передачи. Это довольно легко, даже в сценарии оболочки:
chunk() {
printf '%x\r\n' "${#1}" # Length of the chunk in hex, CRLF
printf '%s\r\n' "$1" # Chunk itself, CRLF
}
chunk $'1\n' # This is a Bash-ism, since it's pretty hard to get a newline
chunk $'2\n' # character portably.
Однако служить это браузер, и вы получите различные результаты в зависимости от браузера. В моей системе Mac OS X 10.5.8 я вижу разные способы взаимодействия между моими браузерами. В бета-версии Safari, Chrome и Firefox 4 я не начинаю видеть вывод до тех пор, пока не отправит около 1000 символов (я бы предположил 1024, включая заголовки, или что-то в этом роде, но я не сузил его до точное поведение). В Firefox 3.6 он начинает отображаться немедленно.
Я бы предположил, что эта задержка вызвана content type sniffing, или character encoding sniffing, которые в процессе стандартизации. Я попытался выяснить, могу ли я обойти задержку, указав правильные типы контента и кодировки символов, но не повезло. Возможно, вам придется отправить некоторые данные заполнения (что было бы довольно легко сделать невидимо, если вы используете HTML вместо обычного текста), чтобы выйти за пределы этого начального буфера.
После того, как вы начнете потоковое использование HTML вместо обычного текста, структура вашего HTML тоже имеет значение. Некоторое содержимое может отображаться постепенно, а некоторые - нет. Например, потоковое вещание <div>
s в тело без стилизации, прекрасно работает и может постепенно отображаться по мере его поступления. Если вы попытаетесь открыть тег <pre>
и просто поместите контент в это, браузеры на базе Webkit будут ждать, пока они не увидят тег close, чтобы попытаться его выложить, в то время как Firefox рад отображать его постепенно. Я не знаю всех угловых дел; вам придется поэкспериментировать, чтобы увидеть, что сработает для вас.
Во всяком случае, я надеюсь, что это поможет вам начать работу. Позвольте мне знать, если у вас есть еще вопросы!
Возможно, вам понадобится Google для «несовпадающих заголовков» –
@glenn: Я сделал это также, но [этот старый FAQ] (http://httpd.apache.org/docs/1.3/misc/FAQ- F.html # nph-scripts) указывает, что «[a] s скриптов Apache 1.3, CGI по существу не буферизованы. Каждый раз, когда ваш скрипт выполняет «флеш» для вывода данных, эти данные передаются клиенту. Некоторые языки сценариев, например Perl, имеют собственную буферизацию для вывода - это можно отключить, установив специальную переменную '$ |' в '1'.» –
Я указал на http://mywiki.wooledge.org/BashFAQ/009 Буферизация оболочки WRT. до сих пор не понял. – hendry