PHP 5.6 可用 fsockopen 发送标准 HTTP POST 请求,需手动构造请求行、头(含 Host 和正确 Content-Length)、空行及请求体,严格使用 \r\n 换行,并分步读取响应头与正文。

PHP 5.6 可以用原生 socket(fsockopen)发送 HTTP POST 请求,无需依赖 cURL 或外部扩展。关键在于手动构造符合 HTTP/1.0 或 HTTP/1.1 规范的请求报文,并正确处理响应头与正文分隔。
构造标准 POST 请求报文
HTTP 协议要求请求由三部分组成:请求行、请求头、空行、请求体。使用 fsockopen 时必须严格遵循格式,尤其注意换行符为 \r\n,结尾需有两个 \r\n(即空行)。
- 第一行写
POST /path HTTP/1.0\r\n(或HTTP/1.1,但若用 1.1 需额外加Host:头) - 必须包含
Content-Length:,值为请求体字节长度(不是字符数,对 UTF-8 中文需用strlen()) - 推荐显式设置
Host:和User-Agent:,避免部分服务端拒绝无 Host 的请求 - 如果发 JSON,
Content-Type应设为application/json;如果发表单数据,则用application/x-www-form-urlencoded
完整可运行示例(PHP 5.6 兼容)
以下代码向 api.example.com:80 发送 JSON 数据:
<?php
$host = 'api.example.com';
$port = 80;
$uri = '/submit';
$body = json_encode(['name' => '张三', 'score' => 95]);
$headers = [
'Content-Type' => 'application/json',
'Host' => $host,
];
$socket = fsockopen($host, $port, $errno, $errstr, 10);
if (!$socket) {
die("连接失败: [$errno] $errstr");
}
// 发送请求行
fwrite($socket, "POST $uri HTTP/1.0\r\n");
// 发送通用头
fwrite($socket, "User-Agent: PHP-Socket-Client/5.6\r\n");
fwrite($socket, "Accept: application/json\r\n");
fwrite($socket, "Content-Length: " . strlen($body) . "\r\n");
// 发送自定义头
foreach ($headers as $key => $val) {
fwrite($socket, "$key: $val\r\n");
}
// 空行分隔头与体
fwrite($socket, "\r\n");
// 发送请求体
fwrite($socket, $body);
// 读取响应(跳过响应头,只取正文)
$response = '';
while (($line = fgets($socket)) !== false) {
if (trim($line) === '') break; // 遇到空行,头结束
}
while (!feof($socket)) {
$response .= fgets($socket, 4096);
}
fclose($socket);
echo $response;
?>
常见问题与修复要点
PHP 5.6 下 socket POST 容易失败,多因协议细节疏漏:
立即学习“PHP免费学习笔记(深入)”;
- 没写 Host 头:HTTP/1.1 必须有,HTTP/1.0 虽非强制,但多数现代 API 会校验
-
Content-Length 错误:不能用
mb_strlen或iconv_strlen,必须用strlen()计算原始字节长度 -
响应解析混乱:不能直接
fgets一次读完,需先按行读至空行,再读正文;否则可能把响应头混入内容 -
HTTPS 不支持:
fsockopen默认不支持 SSL;如需 HTTPS,请改用cURL或升级到 PHP 7+ 后使用stream_socket_client配合ssl://前缀
替代方案建议(更稳更简)
虽然 socket 可行,但 PHP 5.6 已内置稳定可靠的 cURL 扩展,推荐优先使用:
- 自动处理重定向、超时、SSL 验证(可配)、Header 与 Body 分离
- 发 JSON 示例:
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); - 若因环境限制禁用 cURL,才回退到 socket 方案



















