如何使用fscok實現非同步呼叫PHP的代碼案例

來源:互聯網
上載者:User

Web 服務器執行一個指令碼,可能幾毫秒就完成,也可能幾分鐘都完不成。如果程式執行緩慢,使用者可能沒有耐心等下去,就關閉瀏覽器了。

而有的時候,我們更本不關心這些耗時的指令碼的執行結果,但卻還要等他執行完返回,才能繼續下一步。
那麼有沒有什麼辦法,只是簡單的觸發調用這些耗時的指令碼然後就繼續下一步,讓這些耗時的指令碼在服務端慢慢執行?

接下來,我將使用fscokopen來實現這一功能。

PHP是支援socket編程的,就是fsockopen, 在以前做CMS的時候,我也曾經用過它做過smtp發信。
fscokopen返回一個到遠程主機串連的控制代碼。你可以像使用fopen返回的控制代碼一樣,對她進行寫fwrite,讀取fgets, fread等操作。

我們的非同步PHP,主要想要的效果就是,觸發一個PHP指令碼,然後立即返回,留它在伺服器端慢慢執行。前面我也寫過一篇文章討論過這個問題。

那麼,我們就可以使用fsockopen串連到本機伺服器,觸發指令碼執行,然後立即返回,不等待指令碼執行完成。

function triggerRequest($url, $post_data = array(), $cookie = array())…{        $method = "GET";  //可以通過POST或者GET傳遞一些參數給要觸發的指令碼        $url_array = parse_url($url); //擷取URL資訊,以便平湊HTTP HEADER        $port = isset($url_array['port'])? $url_array['port'] : 80;               $fp = fsockopen($url_array['host'], $port, $errno, $errstr, 30);         if (!$fp) …{                return FALSE;        }        $getPath = $url_array['path'] ."?". $url_array['query'];        if(!empty($post_data))…{                $method = "POST";        }        $header = $method . " " . $getPath;        $header .= " HTTP/1.1\r\n";        $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 = strval(NULL);                foreach($cookie as $k => $v)…{                        $_cookie .= $k."=".$v."; ";                }                $cookie_str =  "Cookie: " . base64_encode($_cookie) ." \r\n";//傳遞Cookie                $header .= $cookie_str;        }        if(!empty($post_data))…{                $_post = strval(NULL);                foreach($post_data as $k => $v)…{                        $_post .= $k."=".$v."&";                }                $post_str  = "Content-Type: application/x-www-form-urlencoded\r\n";//POST資料                $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;}

現在,就可以通過這個函數來觸發一個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_shutdown_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]);//註冊指令碼退出時執行的函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.