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

PHP 使用 fsockopen 模擬 HTTP GET/POST 請求完整教學

     編輯:PHP 綜合知識

前言:為什麼需要手動構造 HTTP 請求?

在沒有 cURL 擴展、或需深度控制底層協議細節(如自定 Header、處理特殊重導向)時,PHP 內建的 fsockopen 可直接建立 TCP 連線,手動發送原始 HTTP 封包,實現 GET/POST 模擬請求。

核心函數封裝:sock_get 與 sock_post

以下封裝兩個函數,分別處理 GET 與 POST 請求,支援自定 Query String、Header、Referer、Content-Length 等。

完整程式碼範例

<?php
/**
 * 模擬 HTTP GET 請求
 * @param string $url 目標 URL(含 query string)
 * @param string $query 額外查詢參數(可選)
 */
function sock_get($url, $query = '') {
    $info = parse_url($url);
    $host = $info['host'];
    $port = isset($info['port']) ? $info['port'] : 80;
    $path = $info['path'] ?? '/';
    $queryString = $info['query'] ?? '';
    if ($query) {
        $queryString = $queryString ? $queryString . '&' . $query : $query;
    }

    $fp = fsockopen($host, $port, $errno, $errstr, 3);
    if (!$fp) {
        throw new Exception("連線失敗: $errstr ($errno)");
    }

    $request = "GET $path?$queryString HTTP/1.0\r\n";
    $request .= "Host: $host\r\n";
    $request .= "\r\n";

    fwrite($fp, $request);
    $response = '';
    while (!feof($fp)) {
        $response .= fread($fp, 4096);
    }
    fclose($fp);
    return $response;
}

/**
 * 模擬 HTTP POST 請求
 * @param string $url 目標 URL
 * @param string $query POST 資料(application/x-www-form-urlencoded 格式)
 */
function sock_post($url, $query = '') {
    $info = parse_url($url);
    $host = $info['host'];
    $port = isset($info['port']) ? $info['port'] : 80;
    $path = $info['path'] ?? '/';
    $queryString = $info['query'] ?? '';

    $fp = fsockopen($host, $port, $errno, $errstr, 3);
    if (!$fp) {
        throw new Exception("連線失敗: $errstr ($errno)");
    }

    $request = "POST $path?$queryString HTTP/1.0\r\n";
    $request .= "Host: $host\r\n";
    $request .= "Referer: https://$host$path\r\n";
    $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $request .= "Content-Length: " . strlen($query) . "\r\n";
    $request .= "\r\n";
    $request .= $query;

    fwrite($fp, $request);
    $response = '';
    while (!feof($fp)) {
        $response .= fread($fp, 4096);
    }
    fclose($fp);
    return $response;
}

// 使用範例
$targetUrl = "https://localhost/test.php?uu=rrrrrrrrrrrr";
echo sock_get($targetUrl, "uu=55555555555555555");
echo sock_post($targetUrl, "uu=rrrrrrrrrrrrrrrr");
?>

關鍵細節解析

  • parse_url():解析 URL 為關聯陣列(scheme、host、port、path、query 等),便於組裝 Request-Line 與 Host Header。
  • fsockopen():建立 TCP 連線,最後一個參數為逾時秒數(此處 3 秒)。
  • HTTP 協議格式:請求行(Method Path HTTP/1.0)、Header(每行以 \r\n 結尾)、空行、Body(POST 才有)。
  • Content-Length:POST 必須正確計算 Body 長度,否則伺服器會等待超時。
  • 回應處理:迴圈讀取直到 EOF,取得完整 HTTP 回應(含 Header 與 Body)。

常見坑點與改進建議

  1. HTTPS 不支援:fsockopen 預設只能連 HTTP(port 80)。需用 ssl:// 或 tls:// 前綴並連 port 443,但驗證憑證需額外處理。
  2. Chunked Transfer Encoding:若回應使用分塊傳輸,需自行解析;建議改用 cURL 自動處理。
  3. Keep-Alive 與持久連線:範例使用 HTTP/1.0 且無 Connection: keep-alive,每請求建立新連線,效率較低。
  4. 錯誤處理:生產環境應加入 try-catch、重試機制、詳細日誌記錄。

結語

fsockopen 是理解 HTTP 協議運作的最佳教具,但在實務專案中,強烈建議使用 cURL 或 Guzzle 等成熟 HTTP Client,它們支援 HTTPS、自動重導向、Cookie 管理、多執行緒併發、超時控制等企業級功能,開發效率與穩定性遠超手工 Socket。

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