搜尋
首頁後端開發php教程php深入理解刷新緩衝區函數用法

php深入理解刷新緩衝區函數用法

May 24, 2018 pm 04:26 PM
php函數重新整理深入理解緩衝區

有關php的ob_flush()與flush()使用方法

#注意:ob_flush()和flush()這兩個函數一般要一起使用,順序是先ob_flush(),然後flush(),它們的作用是刷新緩衝區。
這裡具體的說下什麼時候要用到刷新緩衝區和為什麼要刷新緩衝區。

一、什麼時候要刷新緩衝區

當程式中用到file_get_contents()和file_put_contens()這兩個函數時,或程式中執行類似的「讀寫」功能或向瀏覽器執行輸出操作時,會用到ob_flush()和flush()來刷新緩衝區。

二、為什麼要刷新緩衝區

用file_get_contents()和file_put_content()為例來解說。

file_get_contents()和file_put_conents()這兩個函數分別執行讀取資料和寫入資料操作,資料是先被讀到記憶體然後在寫入檔案中的,因為讀取的速度比寫入的速度要快,所以當你的資料被讀完的時候不代表資料也寫入完畢,這個時候多讀的內容就會被暫時放到緩衝區中(記憶體),在這裡需要強調一下,其實資料讀取和寫入是兩個非常快的動作哦。

也用一種解釋(當程式向瀏覽器執行輸出操作時),個別web伺服器程序,特別是Win32下的web伺服器程序,在發送結果到瀏覽器之前,仍然會快取腳本的輸出,直到程式結束為止。如果你不想讓程式執行完畢才輸出,那麼你也可以用到ob_flush()和flush()來刷新快取。

其實,flush()還有一種用途,就是在沒結束程式之前就進行輸出,即一個循環還沒結束就可以把部分結果輸出到瀏覽器上,這個效果很類似ajax的異步傳輸效果。
深入理解ob_flush和flush的區別
ob_flush/flush在手冊中的描述, 都是刷新輸出緩衝區, 並且還需要配套使用, 所以會導致很多人迷惑…
其實, 他們兩​​個的操作物件不同, 有些情況下, flush根本不做什麼事情..
ob_*系列函數, 是操作PHP本身的輸出緩衝區.
所以, ob_flush是刷新PHP自身的緩衝區.
而flush, 嚴格來講, 這個只有在PHP做為apache的Module(handler或者filter)安裝的時候, 才有實際作用. 它是刷新WebServer(可以認為特指apache)的緩衝區.
在apache module的sapi下, flush會透過呼叫sapi_module的flush成員函數指標, 間接的呼叫apache的api: ap_rflush刷新apache的輸出緩衝區, 當然手冊中也說了,有一些apache的其他模組, 可能會改變這個動作的結果..
有些Apache的模組,比如mod_gzip,可能會自己進行輸出緩存,這將導致flush()函數產生的結果不會立即被發送到客戶端瀏覽器。
甚至瀏覽器也會在顯示之前,快取接收到的內容。例如 Netscape瀏覽器會在接受到換行或 html 標籤的開頭之前快取內容,並且在接受到 標記之前,不會顯示整個表格。
一些版本的Microsoft Internet Explorer 只有當接受到的256個位元組以後才開始顯示該頁面,所以必鬚髮送一些額外的空格來讓這些瀏覽器顯示頁面內容所以, 正確使用倆者的順序是.先ob_flush, 然後flush,
當然, 在其他sapi下, 不調用flush也可以, 只不過為了保證你代碼的可移植性, 建議配套使用.

buffer --- - flush()

buffer是一個記憶體位址空間,Linux系統預設大小一般為4096(1kb),即一個記憶體頁。主要用於儲存速度不同步的設備或優先順序不同的 設備之間傳辦理資料的區域。透過buffer,可以讓進程這間的相互等待變少。這裡說一個通俗一點的例子,你打開文字編輯器編輯一個文件的時候,你每輸入一個字符,操作系統並不會立即把這個字符直接寫入到磁盤,而是先寫入到buffer,當寫滿了一個buffer的時候,才會把buffer中的資料寫入磁碟,當然當呼叫核心函數flush()的時候,強制要求把buffer中的髒資料寫回磁碟。
同樣的道理,當執行echo,print的時候,輸出並沒有立即透過tcp傳給客戶端瀏覽器顯示, 而是將資料寫入php buffer。 php output_buffering機制,意義在tcp buffer之前,建立了一新的佇列,資料必須經過該佇列。當一個php buffer寫滿的時候,腳本進程會將php buffer中的輸出資料交給系統核心交由tcp傳給瀏覽器顯示。所以,資料會依序寫到這幾個地方echo/pring -> php buffer -> tcp buffer -> browser
php output_buffering --- ob_flush()
#預設情況下,php buffer是開啟的,而且該buffer預設值是4096,即1kb。你可以透過在php.ini設定檔中找到output_buffering配置.當echo,print等輸出使用者資料的時候,輸出資料都會寫入到php output_buffering中,直到output_buffering寫滿,會將這些數據透過tcp傳送給瀏覽器顯示。你也可以透過 ob_start()手動啟動php output_buffering機制,使得即便輸出超過了1kb數據,也不真的把數據交給tcp傳給瀏覽器,因為ob_start()將php buffer空間設定到了足夠大 。只有直到腳本結束,或呼叫ob_end_flush函數,才會把資料傳送給客戶端瀏覽器。

這兩個函數的使用怕是很多人最迷惑的一個問題,手冊上對兩個函數的解釋也語焉不詳,沒有明確的指出它們的區別,似乎二者的功能都是刷新輸出緩存。但在我們文章一開始的程式碼中如果講fush()替換成ob_flush(),程式就再不能正確執行了。顯然,它們是有區別的,否則也手冊中直接說明其中一個是另一個函數的別名即可了,沒必要分別說明。那麼它們的差別到底是什麼呢?
在沒有開啟快取時,腳本輸出的內容都在伺服器端處於等待輸出的狀態 ,flush()可以將等待輸出的內容立即傳送到客戶端。

開啟快取後,腳本輸出的內容存入了輸出快取中 ,這時沒有處於等待輸出狀態的內容,你直接使用flush()不會向客戶端發出任何內容。而ob_flush()的作用就是將本來存在輸出快取中的內容取出來,設定為等待輸出狀態,但不會直接傳送到客戶端 ,這時你就需要先使用ob_flush()再使用flush(),客戶端才能立即獲得腳本的輸出。

一. flush和ob_flush的正確順序,正確應是,先ob_flush再flush,如下:
ob_flush();
flush();
如果Web伺服器的作業系統是windows系統,那順序顛倒或不使用ob_flush()也不會出現問題。 [有待求證 ] 但是在Linux系統上就無法刷新輸出緩衝。
output buffering函數
1.bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
啟動output_buffering機制。一旦激活,腳本輸出不再直接出給瀏覽器,而是先暫時寫入php buffer記憶體區域。
php預設開啟output_buffering機制,只不過,透過呼叫ob_start()函式資料output_buffering值擴展到足夠 大 。也可以指定$chunk_size來指定output_buffering的值。 $chunk_size預設值是0,表示直到腳本運行結束,php buffer中的資料才會傳送到瀏覽器。如果你設定了$chunk_size的大小 ,表示只要buffer中資料長度達到了該值,就會將buffer中 的資料傳送給瀏覽器。
當然,你可以透過指定$ouput_callback,來處理buffer中的資料。例如函數ob_gzhandler,將buffer中的資料壓縮後再傳送給瀏覽器。
第三個參數:是否擦除緩存,可選,預設是true,如果設定為false,則在腳本執行結束前,快取都不會被清除。
2.ob_get_contents
取得一份php buffer中的資料拷貝。值得注意的是,你應該在ob_end_clean()函數呼叫前呼叫該函數,否則ob_get_contents()傳回一個空字元中。
可以使用ob_get_contents()以字串形式取得服務端快取的數據,
使用ob_end_flush()則會輸出被快取的數據,並關閉快取。
而使用ob_end_clean()則會靜默的清除服務端快取的數據,而不會有任何資料或其他行為。
服務端的快取是堆疊起來的,也就是說你在開啟了ob_start()後,關閉之前,在其內部還 可以開啟另外一個快取ob_start()。
不過你也要務必保證關閉快取的操作和開啟快取的操作數量一樣多。
ob_start() 可以指定一個回呼函數來處理快取資料,如果一個ob_start()內部嵌套了另一個ob_start(),我們假定,外層的ob_start(),編號是A,內層的ob_start()編號是B,它們各自製定了一個回呼函數分別是functionA和functionB,那麼在快取B中的資料輸出時,它會先輩funcitonB回呼函數處理,再交給外層的functionA回呼函數處理,之後才能輸出到客戶端。
另外,手冊說,對於某些web伺服器,例如apache,在使用回調函數有可能會改變程式目前的工作目錄,解決方法是在回呼函數中自行手動把工作目錄修改回來,用chdir函數,這點似乎不常遇到,遇到的時候記得去查手冊吧。
3.ob_end_flush與ob_end_clean
這二個函數有點相似,都會關閉ouptu_buffering機制。但不同的是,ob_end_flush只是把php buffer中的資料衝(flush/send)到客戶端瀏覽器,而ob_clean_clean將php bufeer中的資料清空(erase),但不傳送給客戶端瀏覽器。
ob_end_flush呼叫之前 ,php buffer中的資料依然存在,ob_get_contents()依然可以取得php buffer中的資料拷貝。

而ob_end_flush()呼叫之後 ob_get_contents()取到的是空字串,同時瀏覽器也接收不到輸出,也就是沒有任何輸出。

可以使用ob_get_contents()以字串形式取得服務端快取的數據,使用ob_end_flush()則會輸出被快取的數據,並關閉快取。
而使用ob_end_clean()則會靜默的清除服務端快取的數據,而不會有任何資料或其他行為。

以上是php深入理解刷新緩衝區函數用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
哪些常見問題會導致PHP會話失敗?哪些常見問題會導致PHP會話失敗?Apr 25, 2025 am 12:16 AM

PHPSession失效的原因包括配置錯誤、Cookie問題和Session過期。 1.配置錯誤:檢查並設置正確的session.save_path。 2.Cookie問題:確保Cookie設置正確。 3.Session過期:調整session.gc_maxlifetime值以延長會話時間。

您如何在PHP中調試與會話相關的問題?您如何在PHP中調試與會話相關的問題?Apr 25, 2025 am 12:12 AM

在PHP中調試會話問題的方法包括:1.檢查會話是否正確啟動;2.驗證會話ID的傳遞;3.檢查會話數據的存儲和讀取;4.查看服務器配置。通過輸出會話ID和數據、查看會話文件內容等方法,可以有效診斷和解決會話相關的問題。

如果session_start()被多次調用會發生什麼?如果session_start()被多次調用會發生什麼?Apr 25, 2025 am 12:06 AM

多次調用session_start()會導致警告信息和可能的數據覆蓋。 1)PHP會發出警告,提示session已啟動。 2)可能導致session數據意外覆蓋。 3)使用session_status()檢查session狀態,避免重複調用。

您如何在PHP中配置會話壽命?您如何在PHP中配置會話壽命?Apr 25, 2025 am 12:05 AM

在PHP中配置會話生命週期可以通過設置session.gc_maxlifetime和session.cookie_lifetime來實現。 1)session.gc_maxlifetime控制服務器端會話數據的存活時間,2)session.cookie_lifetime控制客戶端cookie的生命週期,設置為0時cookie在瀏覽器關閉時過期。

使用數據庫存儲會話的優點是什麼?使用數據庫存儲會話的優點是什麼?Apr 24, 2025 am 12:16 AM

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

您如何在PHP中實現自定義會話處理?您如何在PHP中實現自定義會話處理?Apr 24, 2025 am 12:16 AM

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

什麼是會話ID?什麼是會話ID?Apr 24, 2025 am 12:13 AM

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

您如何在無狀態環境(例如API)中處理會議?您如何在無狀態環境(例如API)中處理會議?Apr 24, 2025 am 12:12 AM

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具