使用Fsockopen在PHP中发送Post数据

11

我正在尝试使用fsockopen发送数据,并返回结果。以下是我的当前代码:

<?php
$data="stuff=hoorah\r\n";
$data=urlencode($data);

$fp = fsockopen("www.website.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "POST /script.php HTTP/1.0\r\n";
    $out .= "Host: www.webste.com\r\n";
    $out .= 'Content-Type: application/x-www-form-urlencoded\r\n';
    $out .= 'Content-Length: ' . strlen($data) . '\r\n\r\n';
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?> 

这段代码应该会输出页面内容,而它确实也在输出页面内容,但下面是 script.php 的代码:

<?php
echo "<br><br>";    
$raw_data = $GLOBALS['HTTP_RAW_POST_DATA'];  
 parse_str( $raw_data, $_POST );

//test 1
var_dump($raw_data);
echo "<br><br>":
//test 2
print_r( $_POST );  
?>

结果如下:

HTTP/1.1 200 OK Date: Tue, 02 Mar 2010 22:40:46 GMT Server: Apache/2.2.3 (CentOS) X-Powered-By: PHP/5.2.6 Content-Length: 31 Connection: close Content-Type: text/html; charset=UTF-8 string(0) "" Array ( )

我做错了什么?为什么变量没有传递数据?


1
Curl是免费且开源的软件。Curl采用MIT/X许可证授权。 - Xorlev
9
不能期望每个人(即使是使用共享托管的人)都想要并获得curl。 - Joseph Robidoux
1
你是否启用了always_populate_raw_post_data?http://www.php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data - Tom Haigh
那个关闭了,现在打开看看是否有效。 - Joseph Robidoux
如果您无法使用cURL二进制文件,可以尝试pURL,这是cURL的纯PHP实现。 - m3nda
显示剩余5条评论
10个回答

20

你的代码中有很多小错误。这里是一个经过测试可以正常工作的片段。

<?php

$fp = fsockopen('example.com', 80);

$vars = array(
    'hello' => 'world'
);
$content = http_build_query($vars);

fwrite($fp, "POST /reposter.php HTTP/1.1\r\n");
fwrite($fp, "Host: example.com\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($content)."\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");

fwrite($fp, $content);

header('Content-type: text/plain');
while (!feof($fp)) {
    echo fgets($fp, 1024);
}

然后在 example.com/reposter.php 上放置以下内容

<?php print_r($_POST);

运行时,你应该得到类似以下的输出

HTTP/1.1 200 OK
Date: Wed, 05 Jan 2011 21:24:07 GMT
Server: Apache
X-Powered-By: PHP/5.2.9
Vary: Host
Content-Type: text/html
Connection: close

1f
Array
(
    [hello] => world
)
0

为什么它在末尾显示“1f”和“0”?我也得到了同样的结果,但不太确定。 - carestad
它可以工作,但你需要在fsockopen中更改为fsockopen('www.example.com',80); 并且在fwrite中更改为fwrite($ fp,“Host:www.example.com \ r \ n”); - Julian

1
不错,Tamlyn,效果很好!
对于那些还需要将get变量与url一起发送的人,
//change this:

fwrite($fp, "POST /reposter.php HTTP/1.1\r\n");

//to:

$query = 'a=1&b=2';
fwrite($fp, "POST /reposter.php?".$query." HTTP/1.1\r\n");

1

试试这个:

<?php
$data="stuff=hoorah\r\n";
$data=urlencode($data);

$fp = fsockopen("www.website.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "POST /script.php HTTP/1.0\r\n";
    $out .= "Host: www.webste.com\r\n";
    $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out .= 'Content-Length: ' . strlen($data) . "\r\n\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    fwrite($fp, $data);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?> 

一些字符转义,例如\n在单引号中无法工作。


1

$data 没有被写入套接字。你需要添加类似于:

$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fwrite($fp, $data);

我已经这样做了,但仍然没有成功。 - Joseph Robidoux

1

试试这个替代方案

$out .= 'Content-Length: ' . strlen($data) . '\r\n';
$out .= "Connection: Close\r\n\r\n";
$out .= $data;

尝试在您的服务器上安装数据包嗅探器,查看实际发送到服务器的标头。它们与您在 PHP 中发送的内容相同吗? - Ben Rowe

0

在reposter.php中尝试这个

$raw_data = $GLOBALS['HTTP_RAW_POST_DATA']; 
parse_str( $raw_data, $_POST );

print_r( $_POST );

因为数据不在$_POST[]变量中,而是在$GLOBALS['HTTP_RAW_POST_DATA']变量中。

0
你可以使用这种技术,它可以帮助调用尽可能多的页面,所有页面都将独立运行,而不必等待每个页面的响应,因为它是异步的。 cornjobpage.php //主页
    <?php

post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue");
//post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue2");
//post_async("http://localhost/projectname/otherpage.php", "Keywordname=anyValue");
//call as many as pages you like all pages will run at once independently without waiting for each page response as asynchronous.
            ?>
            <?php

            /*
             * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
             *  
             */
            function post_async($url,$params)
            {

                $post_string = $params;

                $parts=parse_url($url);

                $fp = fsockopen($parts['host'],
                    isset($parts['port'])?$parts['port']:80,
                    $errno, $errstr, 30);

                $out = "POST ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use GET instead of POST if you like
                $out.= "Host: ".$parts['host']."\r\n";
                $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
                $out.= "Content-Length: ".strlen($post_string)."\r\n";
                $out.= "Connection: Close\r\n\r\n";
                fwrite($fp, $out);
                fclose($fp);
            }
            ?>

testpage.php

    <?
    echo $_REQUEST["Keywordname"];//case1 Output > testValue
    ?>

PS:如果您想将URL参数作为循环发送,请遵循此答案:https://dev59.com/dW025IYBdhLWcg3wnXSf#41225209


-1

在某些情况下,Curl 太重了,可以使用 post_to_host():

//GET:
$str_rtn=post_to_host($str_url_target, array(), $arr_cookie, $str_url_referer, $ref_arr_head, 0);

//POST:
$arr_params=array('para1'=>'...', 'para2'=>'...');
$str_rtn=post_to_host($str_url_target, $arr_params, $arr_cookie, $str_url_referer, $ref_arr_head);

//POST with file:
$arr_params=array('para1'=>'...', 'FILE:para2'=>'/tmp/test.jpg', 'para3'=>'...');
$str_rtn=post_to_host($str_url_target, $arr_params, $arr_cookie, $str_url_referer, $ref_arr_head, 2);

//raw POST:
$tmp=array_search('uri', @array_flip(stream_get_meta_data($GLOBALS[mt_rand()]=tmpfile())));
$arr_params=array('para1'=>'...', 'para2'=>'...');
file_put_contents($tmp, json_encode($arr_params));
$arr_params=array($tmp);
$str_rtn=post_to_host($str_url_target, $arr_params, $arr_cookie, $str_url_referer, $ref_arr_head, 3);

//get cookie and merge cookies:
$arr_new_cookie=get_cookies_from_heads($ref_arr_head)+$arr_old_cookie;//don't change the order

//get redirect url:
$str_url_redirect=get_from_heads($ref_arr_head, 'Location');

将 PHP 项目发布到主机位置:http://code.google.com/p/post-to-host/


-2

使用 cURL 是一种选项吗?


-2

抱歉刷新,但对于仍然遇到此类问题的人,请将HTTP/1.0更改为HTTP/1.1,它将起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接