PHP非同步:在PHP中使用 fsockopen curl 實作類別似非同步處理的功能

來源:互聯網
上載者:User
本文僅作為本人學習過程中的一點心得,歡迎大家拍磚。

PHP從主流來看,是一門面向過程的語言,它的最大缺點就是無法實現多線程管理,其程式的執行都是從頭到尾,按照邏輯一路執行下來,不可能出現分支,這一點是限制php在主流程式語言中往更進階的語言發展的原因之一。

在PHP中我們有的時候其實希望在執行某項操作的時候,同時去執行另外一項操作,舉一個情境:在使用者搶票的時候,你並不希望使用者排隊去串連資料庫進行查詢、判斷、插入,完成之後再返回使用者結果。其實我們並不需要使用者等那麼久的時間,使用者提交之後,直接告訴他已經搶票成功了就可以了,至於各種操作,交給後台去處理就好。當然,這種情況我們現在都用訊息列表來處理,把每一個使用者提交的請求存在一個訊息列隊中,告訴使用者已經搞定了,使用者愉快的關掉頁面之後,實際上後台還在一個一個從訊息列隊中取出請求進行操作。我們這篇文章則是通過一種異類的手法,實現操作在後台運行,無需使用者等待。

首先,我們要建立一個請求入口:

  

其次,我們需要一個幕後處理程式,使用者是否線上並不影響它的運行:

  

現在的問題是,在第一段代碼中,如何“提交給後台”?我們通過一種非阻塞式的請求來實現這個功能。也就是建立一個可以被訪問的url,在這個url運行第二段程式,通過一個請求來請求這個url,從而啟用第二段程式自動運行。接下來我們直接看代碼:

// 遠程請求(不擷取內容)函數function _sock($url) {  $host = parse_url($url,PHP_URL_HOST);  $port = parse_url($url,PHP_URL_PORT);  $port = $port ? $port : 80;  $scheme = parse_url($url,PHP_URL_SCHEME);  $path = parse_url($url,PHP_URL_PATH);  $query = parse_url($url,PHP_URL_QUERY);  if($query) $path .= '?'.$query;  if($scheme == 'https') {    $host = 'ssl://'.$host;  }  $fp = fsockopen($host,$port,$error_code,$error_msg,1);  if(!$fp) {    return array('error_code' => $error_code,'error_msg' => $error_msg);  }  else {    stream_set_blocking($fp,true);//開啟了手冊上說的非阻塞模式    stream_set_timeout($fp,1);//設定逾時    $header = "GET $path HTTP/1.1\r\n";    $header.="Host: $host\r\n";    $header.="Connection: close\r\n\r\n";//長串連關閉    fwrite($fp, $header);    usleep(1000); // 這一句也是關鍵,如果沒有這延時,可能在nginx伺服器上就無法執行成功    fclose($fp);    return array('error_code' => 0);  }}

我們建立了一個基於fsockopen的函數,這個函數中利用fsockopen去訪問url,但是在訪問時,並不要求擷取url顯示的內容,而是僅僅發出訪問請求,請求到達後馬上關閉這個訪問。這樣做的好處就是無需再等待被訪問的url是否返回了可靠的資訊,節約了時間,這段代碼的執行時間在0.1-0.2秒之間,對於普通訪客而言,幾乎察覺不到。因此,在使用時,僅需要調用這個函數和對應的url即可。不過,這裡並沒有提供資料轉送的部分,如何傳輸資料,其實只需要在$header中增加post的內容即可。

除了fsockopen,curl其實也可以實現這樣的效果,有些主機上並不支援fsockopen,我們就可以使用curl來實現。

function _curl($url) {  $ch = curl_init();  curl_setopt($ch,CURLOPT_URL,$url);  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);  curl_setopt($ch,CURLOPT_TIMEOUT,1);  $result = curl_exec($ch);  curl_close($ch);  return $result;}

這段代碼的關鍵是提供了一個Timeout,僅1秒鐘,也就是說curl發出請求,無論是否接收到返回的內容,1秒鐘之後都會關閉該訪問,因此這個函數的執行資料為1.0-1.1秒之間。但對於使用者來說,如果是一個需要進行資料處理的應用,1秒中的等待幾乎是被忽略的,如果你希望用一段更簡單和容易被理解的代碼,可以選擇curl來實現。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.