fsockopen(string $hostname, int $port, int &$errno=null, string &$errstr=null, float $timeout=ini_get("default_socket_timeout")): resource|false
回傳檔案指標,可用 fwrite/fread/fgets/fclose 操作。
<?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
}
<?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。
<?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);
$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 | stream_socket_client | cURL |
|---|---|---|---|
| 底層 | 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 等高效能框架。