使用 PHP 底層 fsockopen 手動組裝 HTTP 請求,能深入理解協議細節,適合無 cURL 環境或教學用途。本文提供 GET、POST(含檔案上傳)三種完整可執行範例。
<?php
$host = 'demo.fdipzone.com';
$port = 80;
$errno = $errstr = '';
$timeout = 30;
$url = '/socket/getapi.php';
$param = ['name' => 'fdipzone', 'gender' => 'man'];
$url .= '?' . http_build_query($param);
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$fp) die('Connection failed');
$out = "GET $url HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: close\r\n\r\n";
fputs($fp, $out);
$response = '';
while ($row = fread($fp, 4096)) $response .= $row;
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
echo substr($response, $pos + 4);
?>
<?php
$name = $_GET['name'];
$gender = $_GET['gender'];
echo "name=$name<br>";
echo "gender=$gender";
?>
<?php
$host = 'demo.fdipzone.com';
$port = 80;
$url = '/socket/postapi.php';
$param = ['name' => 'fdipzone', 'gender' => 'man'];
$body = http_build_query($param);
$fp = fsockopen($host, $port, $errno, $errstr, 30);
$out = "POST $url HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "Content-Length: " . strlen($body) . "\r\n";
$out .= "Connection: close\r\n\r\n$body";
fputs($fp, $out);
$response = '';
while ($row = fread($fp, 4096)) $response .= $row;
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
echo substr($response, $pos + 4);
?>
<?php
$host = 'demo.fdipzone.com';
$port = 80;
$url = '/socket/uploadapi.php';
$boundary = '----Boundary' . md5(microtime());
$filePath = '/path/to/test.jpg';
$fileName = 'test.jpg';
$fileType = 'image/jpeg';
$fileContent = file_get_contents($filePath);
$body = "--$boundary\r\n";
$body .= "Content-Disposition: form-data; name=\"file\"; filename=\"$fileName\"\r\n";
$body .= "Content-Type: $fileType\r\n\r\n";
$body .= $fileContent . "\r\n";
$body .= "--$boundary--\r\n";
$fp = fsockopen($host, $port, $errno, $errstr, 30);
$out = "POST $url HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Content-Type: multipart/form-data; boundary=$boundary\r\n";
$out .= "Content-Length: " . strlen($body) . "\r\n";
$out .= "Connection: close\r\n\r\n$body";
fputs($fp, $out);
$response = '';
while ($row = fread($fp, 4096)) $response .= $row;
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
echo substr($response, $pos + 4);
?>
<?php
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
echo "Upload success";
} else {
echo "Upload failed: " . $_FILES['file']['error'];
}
?>
METHOD URL HTTP/1.1\r\n\r\n 分隔 Body。\r\n\r\n 後為實際內容。--boundary 開頭,--boundary-- 結尾,每部分含 Content-Disposition、Content-Type。手寫 Socket HTTP 客戶端是理解 Web 通訊本質的最佳練習。實務開發請改用 cURL 或 Guzzle,享受 HTTPS、重試、並發、流式處理等企業級能力。本範例代碼已精簡至核心邏輯,可直接複製測試。