程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP實時輸出報文到浏覽器

PHP實時輸出報文到浏覽器

編輯:關於PHP編程

Yahoo的前端優化實踐中有一條是先把html裡的<head>部分先輸出(Flush the Buffer Early),這樣做浏覽器得到head後能先下載head裡的css/js文件,而不用等到整個html下載完了才去下載head裡的css/js,從而提高網頁打開的速度。
 
http1.1裡增加了一個Transfer-Encoding: chunked報頭,這個報頭的作用可以把報文分成多塊輸出。
 
報文的格式如下:
Java代碼 
  Chunked-Body = *chunk  
         "0" CRLF  
         footer  
         CRLF   
  chunk = chunk-size [ chunk-ext ] CRLF  
      chunk-data CRLF  
  hex-no-zero = <HEX excluding "0">  
  chunk-size = hex-no-zero *HEX  
  chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )  
  chunk-ext-name = token  
  chunk-ext-val = token | quoted-string  
  chunk-data = chunk-size(OCTET)  
  footer = *entity-header 
 
  Chunked-Body = *chunk
         "0" CRLF
         footer
         CRLF
  chunk = chunk-size [ chunk-ext ] CRLF
      chunk-data CRLF
  hex-no-zero = <HEX excluding "0">
  chunk-size = hex-no-zero *HEX
  chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
  chunk-ext-name = token
  chunk-ext-val = token | quoted-string
  chunk-data = chunk-size(OCTET)
  footer = *entity-header
CRLE:回車換行(\r\n)
例如:
Java代碼 
...                          #很多報頭  
Transfer-Encoding: chunked   #報頭2個CRLE後開始報文  
                               
1                            #chunk的大小,十六進制,然後加個CRLE  
a                            #chunk數據,然後加個CRLE  
4                            #chunk的大小,十六進制,然後加個CRLE  
test                         #chunk數據,可以不斷循環分塊輸出,然後加個CRLE  
0                            #chunk結束,0 + 2個CRLE 
 
...                          #很多報頭
Transfer-Encoding: chunked   #報頭2個CRLE後開始報文
                            
1                            #chunk的大小,十六進制,然後加個CRLE
a                            #chunk數據,然後加個CRLE
4                            #chunk的大小,十六進制,然後加個CRLE
test                         #chunk數據,可以不斷循環分塊輸出,然後加個CRLE
0                            #chunk結束,0 + 2個CRLE
 
 
 
在php裡使用ob_flush後,將自動加上Transfer-Encoding: chunked報頭實現分塊輸出,但是在使用過程中經常達不到效果。不得不考慮一些問題
 
一、php的緩沖區
如果你的php是以apache模塊運行,那請使用flush函數來通知php輸出。如果是以fastcgi模式運行則使用ob_flush通知php。這時gzip將失效,Chunked方式不支持每塊都獨立壓縮。只能全部輸出壓縮後,將壓縮包分塊輸出。為了保證兼容性,先調用ob_flush,再調用flush。
 
二、浏覽器的緩沖區
當遇到Transfer-Encoding: chunked報頭後,浏覽器做什麼反應,這個還是要看浏覽器的實現了。在我的實驗中,firefox不管chunk數據大小都會做實時顯示,而ie8和chrome則需要一定長度後才顯示。所以,需要先輸出一定的大小後某些浏覽器才有效果。
 
三、反向代理服務器
你使用的反向代理服務器支持http1.1協議嗎?它是怎麼處理後端是chunked方式的?proxy緩沖沒滿之前遇到chunked會按照後端來輸出嗎?
 
nginx的proxy功能只支持http1.0,並且它只有proxy buffer滿了才會輸出。
 
四、FastCGI緩沖
如果以FastCGI模式運行,可能Web Server有自己的fastcgi緩沖,等待緩沖滿了才輸出(nginx就這樣)。flush函數只能通知php的output緩沖輸出

Chunked transfer encoding
Hypertext Transfer Protocol -- HTTP/1.1 Chunked transfer encoding
深入理解ob_flush和flush的區別

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved