我在PHP中使用套接字连接将数据发布到Apache Web服务器。我对这种技术有点新意,我不知道如何将标题与响应主体隔离开来。
发送代码:
<?php
// collect data to post
$postdata = array(
'hello' => 'world'
);
$postdata = http_build_query($postdata);
// open socket, send request
$fp = fsockopen('127.0.0.1', 80);
fwrite($fp, "POST /server.php HTTP/1.1\r\n");
fwrite($fp, "Host: fm1\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($postdata)."\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");
fwrite($fp, $postdata);
// go through result
$result = "";
while(!feof($fp)){
$result .= fgets($fp);
}
// close
fclose($fp);
// display result
echo $result;
?>
服务器代码:
Hello this is server. You posted:
<pre>
<?php print_r($_POST); ?>
</pre>
发布到一台服务器时,我得到:
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 09:55:27 GMT
Server: Apache/2.2.15 (Win32) mod_ssl/2.2.15 OpenSSL/0.9.8m PHP/5.3.2
X-Powered-By: PHP/5.3.2
Content-Length: 79
Connection: close
Content-Type: text/html
Hello this is server. You posted:
<pre>
Array
(
[hello] => world
)
</pre>
正如所料。我想剥去标题,然后从“Hello this is server .....”开始阅读正文。 如何可靠地检测标题的结尾并将正文读入变量?
另外,我在回复中测试了另一台服务器:
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 10:02:04 GMT
Server: Apache/2
X-Powered-By: PHP/5.2.17
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
4d
Hello this is server. You posted:
<pre>
Array
(
[hello] => world
)
</pre>
0
正文周围的“4d”和“0”是什么?
谢谢!
在有人说使用CURL之前PS,我不能不幸: - (答案 0 :(得分:16)
您可以通过拆分双线换行来将标题与正文分开。它应该是<CRLF><CRLF>
所以通常工作:
list($header, $body) = explode("\r\n\r\n", $response, 2);
更可靠的是,您应该使用正则表达式来捕捉换行符(超级不太可能发生):
list($header, $body) = preg_split("/\R\R/", $response, 2);
4d
和0
的内容称为chunked encoding。 (它是以另一个换行符分隔的十六进制数字,并且不包含以下原始内容块的长度。)
要清除它,您必须先查看标题,然后查看是否有相应的Transfer-Encoding:
条目。这是复杂的,并且建议使用无数现有的HTTP用户空间处理类之一。梨has one。
答案 1 :(得分:0)
标题应以"\r\n\r\n"
结尾(两次)。这些 4d 和 0 可能是您的php响应的一部分(它们不是标题的一部分)。
答案 2 :(得分:0)
在大多数情况下,Mario的答案应该有效,但我刚尝试将此方法应用于Couch DB的响应,并且在某些情况下它不起作用。
如果响应中不包含任何文档,那么Couch DB会在响应正文中放置“\ r \ n \ r \ n”来尝试保持结果格式良好,在这种情况下仅通过“\ r \ n拆分响应是不够的\ n \ r \ n“因为你可能会意外地切断身体的末端部分。
HTTP/1.0 200 OK Server: CouchDB/1.6.1 (Erlang OTP/R16B02) ETag: "DJNMQO5WQIBZHFMDU40F1O94T" Date: Mon, 06 Jul 2015 09:37:33 GMT Content-Type: text/plain; charset=utf-8 Cache-Control: must-revalidate
{"total_rows":0,"offset":0,"rows":[
// Couch DB adds some extra line breakers on this line
]}
对于Couch DB,解析后似乎更可靠:
$parts = explode("\r\n\r\n", $response);
if ($parts)
{
$headers = array_shift($parts);
$body = json_decode(implode("\r\n\r\n", $parts));
}