首頁  >  文章  >  後端開發  >  php非同步:在php中使用fsockopen curl實作類似非同步處理的功能方法

php非同步:在php中使用fsockopen curl實作類似非同步處理的功能方法

巴扎黑
巴扎黑原創
2016-12-22 14:15:371526瀏覽

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

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

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

提交的資料 

提交給後台 

告訴用戶已經搞定了  

告訴用戶已經搞定了  

不影響它的運作:

<?php 
ignore_user_abort(true);
set_time_limit(0);

過來的資料

資料處理 

現在的問題是,在第一段程式碼中,如何「提交給後台」?我們透過一種非阻塞式的請求來實現這個功能。也就是創建一個可以被存取的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 .= &#39;?&#39;.$query;
 if($scheme == &#39;https&#39;) {
  $host = &#39;ssl://&#39;.$host;
 }
 
 $fp = fsockopen($host,$port,$error_code,$error_msg,1);
 if(!$fp) {
  return array(&#39;error_code&#39; => $error_code,&#39;error_msg&#39; => $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(&#39;error_code&#39; => 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來實現。


🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn