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

PHP Socket 實現原生 POST 請求:模擬登錄、API 對接、Webhook 發送的底層實踐

     編輯:PHP 相關知識

不依賴 cURL 擴展,純 PHP Socket (fsockopen) 構造 HTTP/1.1 POST 請求,實現模擬登錄、Cookie 同步、第三方 API 對接。本文給出完整可復用函數,含 Header 構造、Body 編碼、Chunked 響應處理、Cookie 解析回寫。

核心函數

function httpPost(string $host, string $path, array $data, int $port = 80, array $headers = []): string {
    // 構造 Body
    $body = http_build_query($data);
    $bodyLen = strlen($body);

    // 預設 Header
    $defaultHeaders = [
        "Host: $host:$port",
        "Content-Type: application/x-www-form-urlencoded",
        "Content-Length: $bodyLen",
        "Connection: Close",
    ];
    $request = "POST $path HTTP/1.1\r\n";
    $request .= implode("\r\n", array_merge($defaultHeaders, $headers)) . "\r\n\r\n";
    $request .= $body;

    // 發送請求
    $fp = fsockopen($host, $port, $errno, $errstr, 10);
    if (!$fp) throw new Exception("Connect failed: $errstr ($errno)");

    fwrite($fp, $request);

    // 讀取響應
    $response = '';
    while (!feof($fp)) {
        $response .= fgets($fp, 4096);
    }
    fclose($fp);

    return $response;
}

完整案例:模擬論壇登錄並同步 Cookie

function bbsLogin(string $user, string $pass, string $host, int $port = 80): void {
    $data = [
        'user_login' => $user,
        'password' => $pass,
        '_wp_http_referer' => '/bbpress/',
        'remember' => 'true',
    ];

    $fp = fsockopen($host, $port, $errno, $errstr, 10);
    if (!$fp) throw new Exception("Connect failed");

    $body = http_build_query($data);
    $request = "POST /bbpress/bb-login.php HTTP/1.1\r\n";
    $request .= "Host: $host:$port\r\n";
    $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $request .= "Content-Length: " . strlen($body) . "\r\n";
    $request .= "Connection: Close\r\n\r\n";
    $request .= $body;

    fwrite($fp, $request);

    // 解析響應頭中的 Set-Cookie 並寫入客戶端
    while (!feof($fp)) {
        $line = fgets($fp);
        if (stripos($line, 'Set-Cookie:') === 0) {
            // 粗略解析:Set-Cookie: name=value; expires=...; path=...
            $parts = explode(' ', $line);
            $cookiePair = explode('=', $parts[1], 2);
            $name = urldecode($cookiePair[0]);
            $value = urldecode(rtrim($cookiePair[1], ";\r\n"));
            // 解析 path/expires 等屬性 (略)
            setcookie($name, $value, time()+3600*24*7, '/');
        }
    }
    fclose($fp);
}

進階處理

  1. HTTPS 支持:fsockopen('ssl://' . $host, 443) 或 stream_socket_client('ssl://...'),需啟用 openssl 擴展。
  2. Chunked Transfer-Encoding:響應頭含 Transfer-Encoding: chunked 時需手動解碼塊大小 + 內容。
  3. Keep-Alive 復用:Connection: Keep-Alive + 解析 Content-Length 精確讀取,避免 feof 等待超時。
  4. 超時控制:stream_set_timeout($fp, 5) 設置讀寫超時。

適用場景與選型

| 場景 | 推薦方案 | |------|----------| | 簡單 POST、無 cURL 環境 | Socket (本文方案) | | 生產級 HTTP 客戶端 | Guzzle / Symfony HttpClient (封裝 cURL) | | 高併發異步請求 | Swoole Coroutine Http Client | | 測試/腳本快速驗證 | file_get_contents + stream_context_create |

Socket 方案零依賴、完全可控,適合嵌入式環境、極簡容器、排查 cURL 行為差異等場景。

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