PHP fsockopen 模拟 POST/GET 请求实战
在 PHP 环境中,除了 cURL 之外,fsockopen 提供了一种更底层的方案来模拟 HTTP 客户端。本指南将演示如何构建标准的 HTTP 请求包,以向指定 URL 提交 GET 查询参数或 POST 表单数据,并接收服务器响应。
准备条件与原理分析
fsockopen 基于 TCP/IP 建立连接。要成功发起 HTTP 请求,必须严格按照 HTTP/1.1 协议规范拼接报文:
- GET 请求:参数直接追加至 URL Query String 中。
- POST 请求:参数需放入 Request Body,并在 Header 中声明
Content-Length及Content-Type: application/x-www-form-urlencoded。
第 1 步:编写 GET 请求函数
目的:构建 GET 头部并获取响应。
入口:目标 URL 字符串及关联的查询数组。
$arr = array(
'user' => 'test',
'password' => ''
);
// 调用示例
sock_get('http://example.com/api', $arr);
function sock_get($url, $query = array()) {
// 1. 解析 URL 结构
$info = parse_url($url);
// 2. 提取端口号,默认为 80
$port = isset($info['port']) ? $info['port'] : 80;
// 3. 组合查询字符串,注意避免重复参数
$query_str = http_build_query($query);
if (!empty($info["query"])) {
$query_str .= '&' . $info["query"];
}
// 4. 建立网络连接
$fp = fsockopen($info["host"], $port, $errno, $errstr, 30);
if (!$fp) {
return FALSE; // 连接失败返回假值
}
// 5. 组装 HTTP 头
$head = "GET " . $info['path'] . "?" . trim($query_str) . " HTTP/1.1\r\n";
$head .= "Host: " . $info['host'] . "\r\n";
$head .= "Connection: Close\r\n"; // 明确关闭连接
$head .= "\r\n";
// 6. 发送请求头
fputs($fp, $head);
// 7. 循环读取响应内容
$response = "";
while(!feof($fp)) {
$line = fgets($fp, 1024);
$response .= $line;
}
fclose($fp);
return $response;
}
第 2 步:编写 POST 请求函数
目的:构建 POST 头部与 Body,并提交表单数据。
重要参数:Body 长度必须准确匹配。
完成状态:完整输出 HTML 响应源码。
// 调用示例
sock_post('http://example.com/login', $arr);
function sock_post($url, $data = array()) {
// 1. 格式化数据为 form-encoded 格式
$query = http_build_query($data);
$info = parse_url($url);
// 默认端口 80
$fp = fsockopen($info["host"], 80, $errno, $errstr, 30);
// 2. 组装复杂的请求头
$head = "POST " . $info['path'] . (isset($info['query']) ? '?' . $info['query'] : '') . " HTTP/1.1\r\n";
$head .= "Host: " . $info['host'] . "\r\n";
$head .= "Content-type: application/x-www-form-urlencoded\r\n";
$head .= "Content-Length: " . strlen($query) . "\r\n";
$head .= "Connection: Close\r\n";
$head .= "\r\n";
// 3. 拼接 Body 并发送
$head .= $query;
fputs($fp, $head);
// 4. 接收响应
$response = "";
while (!feof($fp)) {
$line = fgets($fp, 1024);
$response .= $line;
}
fclose($fp);
return $response;
}
注意事项与排错
- 超时设置:
fsockopen第四个参数为超时秒数,建议设置为非零值(如 30),防止脚本永久挂起。 - 协议版本:HTTP/1.1 要求必须包含 Host 字段;若省略 Connection 头,部分服务端可能保持长连接导致读取阻塞。
- 返回值差异:上述代码返回的是包含 HTTP 头部的完整响应体。若仅需正文,需过滤掉双换行符之前的头部信息。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













