stream_set_blocking

stream_set_blocking ($resource, $flag); $flag 取值爲0或1 數組

0是非阻塞,1是阻塞 網絡

阻塞的意義是什麼呢? 併發

某個函數讀取一個網絡流,當沒有未讀取字節的時候,程序該怎麼辦? 異步

是一直等待,直到下一個未讀取的字節的出現,仍是當即告訴調用者當前沒有新內容? 函數

前者是阻塞的,後者是非阻塞的。 spa

阻塞的好處是,排除其它非正常因素,阻塞的是按順序執行的同步的讀取。 server

借用小說裏的說法就是「神刀出鞘,無血不歸」。在讀到新內容以前,它不會往下走,什麼別的事情都不作。 隊列

而非阻塞,由於沒必要等待內容,因此能異步的執行,如今讀到讀不到都不要緊,執行讀取操做後馬上就繼續往下作別的事情。 get

若是你不放心,能夠過必定的時間再來檢查執行的結果。以前我寫過一個用popen pclose來讓程序併發執行的例子。 同步

當時的遺憾就是調用以後無論,因此無法知道程序是否執行成功了。如今popen以後設定爲非阻塞模式,就能夠建立一個數組做爲任務池。
使用一個while(1)的「死循環」來檢查當前任務池中各個任務的狀態,有老任務執行完畢時,$status = stream_get_meta_data($resource);
狀態值$status['eof']爲真,就表示那個任務執行完畢了。我本次實現的程序功能比較單一,只須要知道它執行完畢就能夠了。若是你的任務有多種結果,那就繼續分析讀取到的內容吧。發現有任務執行完畢,從任務池中剔除該任務,若是任務隊列中還有未作的任務,就把新任務從隊列中移到任務池中執行。

說的比較囉嗦,若是你用過網絡螞蟻或網際快車之類的下載軟件,你會發現我講的這些其實就是它們的工做原理。



PHP函數stream_set_timeout(Stream Functions)做用於讀取流時的時間控制。fsockopen函數的timeout只管建立鏈接時的超時,對於鏈接後讀取流時的超時,則須要用到 stream_set_timeout函數。因爲國內的網絡環境不是很穩定,尤爲是鏈接國外的時候,不想程序出現Fatal error: Maximum execution time of 30 seconds exceeded in …的錯誤,該函數尤爲有用。stream_set_timeout需配合stream_get_meta_data使用,若是沒有timeout, stream_get_meta_data返回數組中time_out爲空,反之爲1,可根據此判斷是否超時。另外因爲PHP默認的Maximum execution time爲30秒,這是一次執行週期的時間,爲了避免出現上述的Fatal error,還須要設置一個總的讀取流的時間,具體方法參見下面詳細代碼。 


$server="www.yahoo.com";
$port = 80;

$data="GET / HTTP/1.0rn";
$data.="Connection: Closern";
$data.="User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)rnrn";

$start_time = time();
$fp= fsockopen ($server, $port, $errno, $errstr, 5);
if (!$fp) {
die("Connect Timeout.n");
} else {
stream_set_blocking($fp, True);
stream_set_timeout($fp, 3);

fputs($fp, "$data");
while (!feof($fp)) {
$text .= fread($fp, 2000);

$diff = time() - $start_time;
if ($diff > 24) {
die("Timeout!n");
}

$status = stream_get_meta_data($fp);
if ($status[’timed_out’]) {
die("Stream Timeout!n");
}
}
}

fclose($fp);
?>
相關文章
相關標籤/搜索