深入PHP非同步執行的詳解

2022-09-29 13:54:11 字數 3077 閱讀 5132

web伺服器執行乙個php指令碼,有時耗時很長才能返回執行結果,後面的指令碼需要等待很長一段時間才能繼續執行。如果想實現只簡單觸發耗時指令碼的執行而不等待執行結果就直接執行下一步操作,可以通過fscokopen函式來實現。

php支援socket程式設計,fscokopen函式返回乙個到遠端主機連線的控制代碼,可以像使用fopen返回的控制代碼一樣,對它進行fwrite、fgets、fread等操作。使用fsockopen連線到本地伺服器,觸發指令碼執行,然後立即返回,不等待指令碼執行完成,即可實現非同步執行php的效果。

示例**如下:

複製** **如下:

$header .= "host: ". $url_array['host'] . "\r\n "; //http 1.1 host域不能省略

/*以下頭資訊域可以程式設計客棧省略

$header .= "user-agent: mozilla/5.0 (windows; u; windows nt 5.1; en-us; rv:1.8.1.13) gecko/20080311 firefox/2.0.0.13 \r\n";

$header .= "accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,q=0.5 \r\n";

$header .= "accept-language: en-us,en;q=0.5 ";

$header .= "accept-encoding: gzip,deflate\r\n";

*/$header .= "connection:close\r\n";

if(!empty($cookie))

$cookie_str =  "cookie: " . base64_encode($_cookie) ." \r\n"; //傳遞cookie

$header .= $cookie_str;

}if(!empty($post_data))

$post_str  = "content-type: application/x-www-form-urlencoded\r\n";

$post_str .= "content-length: ". strlen($_post) ." \r\n"; //post資料的長度

$post_str .= $_post."\r\n\r\n "; //傳遞post資料

$header .= $post_str;

}fwrite($fp, $header);

//echo fread($fp, 1024); //伺服器返回

fclose($fp);

return true;

}  

這樣就可以通過fsockopen()函式來觸發乙個php指令碼的執行,然後函式就會返回。 接著執行下一步操作了。

現在存在乙個問題:當客戶端斷開連線後,也就是triggerrequest傳送請求後,立即關閉了連線,那麼可能會引起伺服器端正在執行的指令碼退出。

在 php 內部,系統維護著連線狀態,其狀態有三種可能的情況:

* 0 – normal(正常)

* 1 – aborted(異常退出)

* 2 – timeout(超時)

當 php 指令碼正常地執行 normal 狀態時,連線為有效。當客戶端中斷連線時,aborted 狀態的標記將會被開啟。遠端客戶端連線的中斷通常是由使用者點選 stop 按鈕導致的。當連線時間超過 php 的時限(參閱 set_time_limit() 函式)時,timeout 狀態的標記將被開啟。

可以決定指令碼是否需要在客戶端中斷連線時退出。有時候讓指令碼完整地執行會帶來很多方便,即使沒有遠端瀏覽器接受指令碼的輸出。預設的情況是當遠端客戶端連線 中斷時指令碼將會退出。該處理過程可由 php.ini 的 ignore_user_abort 或由 apache .conf 設定中對應的"php_value ignore_user_abort"以及 ignore_user_abort() 函式來控制。如果沒有告訴 php 忽略使用者的中斷,指令碼將會被中斷,除非通過 register_shutd程式設計客棧own_function() 設定了關閉觸發函式。通過該關閉觸發函式,當遠端使用者點選 stop 按鈕後,指令碼再次嘗試輸出資料時,php 將會檢測到連線已被中斷,並呼叫關閉觸發函式。

指令碼也有可能被內建的指令碼計時器中斷。預設的超時限制為 30 秒。這個值可以通過設定 php.ini 的 max_execution_time 或 apache .conf 設定中對應的"php_value max_execution_time"引數或者 set_time_limit() 函式來更改。當計數器超時的時候,指令碼將會類似於以上連線中斷的情況退出,先前被註冊過的關閉觸發函式也將在這時被執行。在該關閉觸發函式中,可以通過呼叫 connection_status() 函式來檢查超時是否導致關閉觸發函式被呼叫。如果超時導致了關閉觸發函式的呼叫,該函式將返回 2。

需要注意的一點是 aborted 和 timeout 狀態可以同時有效。這在告訴 php 忽略使用者的退出操作時是可能的。php 將仍然注意使用者已經中斷了連線但指令碼仍然在執行的情況。如果到了執行的時間限制,指令碼將被退出,設定過的關閉觸發函式也將被執行。在這時會發現函式 connection_status() 返回 3。

所以還在要觸發的指令碼中指明:

複製** **如下:

ignore_user_abort(true);//如果客戶端斷開連線,不會引起指令碼abort

set_time_limit(0);//取消指令碼執行延時上限

或使用:

register_shutdown_function(callback fuction[, parameters]);//註冊指令碼退出時執行的函式

本文標題: 深入php非同步執行的詳解

本文位址:

深入PHP執行環境配置的詳解

執行環境配置 php54 apache2.2 mysql 1.預設埠設定 listen 12.34.56.78 80 listen 8080 2.載入模型 loadmodule php5 module d myziliao php php54zyqusmahjphp5apache2 2.dll 3....

php 非同步執行

header host url array host r n http 1.1 host域不能省略 header connection close r n r n header connection close r n r n if empty post data out connection cl...

PHP非同步執行問題

php在執行exec 方法時,會等待exec方法完全執行完之後才會繼續執行其餘 而exec 會執行很長時間,這樣的話頁面就會一直處於等待狀態,等exec執行完之後才會重新整理,所以有沒有某種方法可以使exec在後台執行的同時,讓頁面不用等待exec執行完畢就重新整理?嘗試在被執行的指令後面加個 但並...