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

PHP fsockopen 實戰:建立 TCP 連線、發送 HTTP 請求、Socket 服務端

     編輯:PHP 綜合知識

fsockopen 基礎語法

fsockopen(string $hostname, int $port, int &$errno=null, string &$errstr=null, float $timeout=ini_get("default_socket_timeout")): resource|false

回傳檔案指標,可用 fwrite/fread/fgets/fclose 操作。

範例 1:簡易 HTTP GET 客戶端

<?php
$fp = fsockopen('127.0.0.1', 80, $errno, $errstr, 5);
if (!$fp) {
    die("連線失敗:$errstr ($errno)");
}

// 發送 HTTP/1.0 請求(無 Host 標頭較舊但簡單)
fwrite($fp, "GET / HTTP/1.0\r\n\r\n");

// 設定讀取逾時
stream_set_timeout($fp, 2);

$response = fread($fp, 2000);
$meta = stream_get_meta_data($fp);
fclose($fp);

if ($meta['timed_out']) {
    echo "讀取逾時";
} else {
    echo $response; // 含 Header + Body
}

範例 2:簡易 TCP 服務端

<?php
$socket = stream_socket_server('tcp://0.0.0.0:8000', $errno, $errstr);
if (!$socket) die("$errstr ($errno)");

echo "服務啟動於 8000 埠...\n";
while ($conn = stream_socket_accept($socket)) {
    $time = date('n/j/Y g:i a');
    fwrite($conn, "Current time: $time\n");
    fclose($conn);
}
fclose($socket);

測試:telnet 127.0.0.1 8000 或 nc 127.0.0.1 8000。

範例 3:非阻塞連線與逾時檢測

<?php
$fp = fsockopen('127.0.0.1', 80, $errno, $errstr, 5);
if (!$fp) die("連線失敗");

stream_set_blocking($fp, 0); // 非阻塞
// 發送請求
fwrite($fp, "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n");

// 使用 stream_select 等待可讀/可寫/異常
$read = $write = $except = [$fp];
$ready = stream_select($read, $write, $except, 5); // 5 秒逾時

if ($ready === 0) {
    echo "連線逾時";
} elseif ($ready > 0) {
    if ($read) {
        $data = '';
        while (!feof($fp)) $data .= fread($fp, 8192);
        echo $data;
    }
}
fclose($fp);

進階:SSL/TLS 連線

$fp = fsockopen('ssl://api.example.com', 443, $errno, $errstr, 10);
// 或
$fp = stream_socket_client('ssl://api.example.com:443', $errno, $errstr, 10);

需 PHP 開啟 openssl 擴展。可用 stream_context_set_option() 驗證憑證、設定 SNI。

常見問題

現象解決
連線被拒絕目標埠未監聽、防火牆攔截、IP 錯誤
讀取到空字串對端已關閉連線、或 HTTP 響應為 chunked 需解析
中文亂碼確認雙方編碼一致,HTTP 標頭 Content-Type: ...; charset=utf-8
大檔案傳輸記憶體爆增改用 stream_copy_to_stream($fp, STDOUT) 直接管道輸出

fsockopen vs cURL vs Stream Socket Client

特性fsockopenstream_socket_clientcURL
底層PHP 內建PHP Stream 封裝libcurl
HTTP 協議支援手動構建手動構建完整(重導向、Cookie、認證、多協議)
SSL/TLS支援支援完整
非阻塞/事件驅動stream_set_blocking + stream_select原生支援cURL multi
效能中中高(連線池、Keep-Alive)

總結

fsockopen 是 PHP 底層網路編程的入口,適合教學、簡易客戶端、自定義協議。生產環境 HTTP 請求強烈建議使用 cURL 或 Guzzle;長連線/高併發服務端請用 stream_socket_server + stream_select 或 Swoole/RoadRunner 等高效能框架。

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