allow_url_fopen、無 cURL 擴展時的備選<?php
function socketGet($url, &$ret) {
$urlArr = parse_url($url);
$host = $urlArr['host'];
$port = isset($urlArr['port']) ? $urlArr['port'] : 80;
$path = isset($urlArr['path']) ? $urlArr['path'] : "/";
$fp = fsockopen($host, $port, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
return false;
}
$out = "GET $path HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
$ret = "";
fwrite($fp, $out);
while (!feof($fp)) {
$ret .= fgets($fp, 128);
}
fclose($fp);
return true;
}
// 使用
$html = '';
socketGet('https://www.example.com/', $html);
echo $html;
?>
<?php
function socketPost($url, $data, &$ret) {
$urlArr = parse_url($url);
$host = $urlArr['host'];
$port = isset($urlArr['port']) ? $urlArr['port'] : 80;
$path = isset($urlArr['path']) ? $urlArr['path'] : "/";
$fp = fsockopen($host, $port, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
return false;
}
$out = "POST $path HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "Content-Length: " . strlen($data) . "\r\n";
$out .= "Connection: Close\r\n\r\n"; // 若 Keep-Alive 導致掛起,改為 Close
$out .= $data;
$ret = "";
fwrite($fp, $out);
while (!feof($fp)) {
$ret .= fgets($fp, 128);
}
fclose($fp);
return true;
}
// 使用
$postData = "username=test&password=123456";
$response = '';
socketPost('https://www.example.com/login.php', $postData, $response);
echo $response;
?>
| 項目 | GET | POST |
|---|---|---|
| 請求行 | GET /path HTTP/1.1 | POST /path HTTP/1.1 |
| Host 頭 | 必須(HTTP/1.1 強制) | 必須 |
| Content-Type | 無 | application/x-www-form-urlencoded |
| Content-Length | 無 | Body 字節長度 |
| Connection | Close(簡單斷開) | Close(避免 Keep-Alive 讀取掛起) |
| Body | 無 | URL 編碼的鍵值對字符串 |
\r\n\r\n 分離HTTP/1.1 200 OK、Content-Type、Content-Length、Set-Cookie 等Transfer-Encoding: chunked)需手動解碼塊大小fsockopen('ssl://host', 443) 或 stream_socket_client + SSL 上下文除非極特殊場景,優先使用 cURL 或 Guzzle:支持重試、超時控制、並發、Cookie 管理、代理、HTTP/2、證書驗證等企業級特性。Socket 手寫僅作教學或極簡環境應急。