首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 使用 fsockopen 實現非同步腳本執行

     編輯:PHP 相關知識

利用 fsockopen 達到 PHP 非同步呼叫效果

PHP 原生不支援多執行緒,但可透過 fsockopen() 發送 HTTP 請求後不等待回應,模擬非同步執行。常用於背景處理耗時任務(如發送郵件、資料同步、日誌記錄),避免阻塞主程式流程。

核心函式:request_by_fsockopen()

<?php
function request_by_fsockopen($url, $post_data = array(), $debug = false) {
    $url_array = parse_url($url);
    $host = $url_array['host'];
    $port = isset($url_array['port']) ? $url_array['port'] : 80;
    $path = $url_array['path'] . (isset($url_array['query']) ? '?' . $url_array['query'] : '');

    $fp = fsockopen($host, $port, $errno, $errstr, 10);
    if (!$fp) {
        echo "$errstr ($errno)";
        return false;
    }

    $method = empty($post_data) ? 'GET' : 'POST';
    $header = "$method $path HTTP/1.1\r\n";
    $header .= "Host: $host\r\n";

    if (!empty($post_data)) {
        $post_str = http_build_query($post_data);
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($post_str) . "\r\n";
        $header .= "Connection: Close\r\n\r\n";
        $header .= $post_str;
    } else {
        $header .= "Connection: Close\r\n\r\n";
    }

    fwrite($fp, $header);

    // 除錯模式:讀取回應(會阻塞,失去非同步效果)
    if ($debug) {
        $response = '';
        while (!feof($fp)) {
            $response .= fgets($fp);
        }
        echo $response;
    }

    fclose($fp);
    return true;
}
?>

使用範例

主程式 main.php

<?php
require 'async_helper.php'; // 包含上述函式

$data = array('name' => 'guoyu', 'pwd' => '123456');
$url = 'https://localhost/test/other.php';

// 非同步呼叫,第三參數設 false 不等待回應
request_by_fsockopen($url, $data, false);

echo '主程式繼續執行,不等待 other.php 完成。';
?>

被呼叫腳本 other.php

<?php
header('Content-Type: text/html; charset=utf-8');
$name = isset($_POST['name']) ? $_POST['name'] : '';
$pwd  = isset($_POST['pwd']) ? $_POST['pwd'] : '';

// 模擬耗時操作
sleep(5);
file_put_contents('async_log.txt', "[$name] processed at " . date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);

echo "success ok";
?>

運作原理

  1. 主程式透過 fsockopen 建立 TCP 連線至目標 URL。
  2. 組裝 HTTP 請求標頭與 POST 資料並發送。
  3. 若 $debug = false,立即關閉連線 fclose($fp),不讀取回應,達成「發後即忘」。
  4. 目標腳本在獨立的 PHP 進程中執行,互不干擾。

注意事項與替代方案

  • 可靠性:無法保證目標腳本一定執行成功,生產環境建議搭配訊息佇列(如 RabbitMQ、Redis Queue)或 exec() 背景執行 CLI 腳本。
  • HTTPS:fsockopen 需手動處理 SSL,建議改用 stream_context_create() 搭配 file_get_contents() 或 cURL 非同步模式。
  • 超時控制:第 5 參數 10 秒為連線超時,可依需求調整。

進階:使用 cURL 非同步(推薦)

<?php
function async_curl_post($url, $data) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($data),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => 1,      // 1 毫秒即返回,不等待回應
        CURLOPT_NOSIGNAL => 1,        // 避免訊號干擾
        CURLOPT_HEADER => false,
    ]);
    curl_exec($ch);
    curl_close($ch);
}
?>

cURL 設定極短逾時即可達到類似效果,且支援 HTTPS、更穩定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved