发送POST请求而不等待响应?

时间:2010-02-03 09:23:16

标签: php libcurl

我正在编写一个简单的REST服务,它响应来自客户端的请求。全部用PHP。

我担心的是,当我的服务器响应请求时,如果客户端发送回“ok”响应的速度太慢,最终可能会占用资源。

如何通过lib_curl发送POST请求,将其设置为不等待任何响应,而是在POST数据发送后立即退出?

这甚至可能吗?谢谢!

8 个答案:

答案 0 :(得分:17)

您无法在未收到HTTP回答的情况下发送数据。 HTTP总是请求 - >响应。即使响应非常短(如简单的200没有文本),也需要有响应。每个HTTP套接字都会等待响应。

如果您不关心响应,可以向发出请求的服务器添加一个进程,然后只需请求数据推送到它(就像正在运行的服务一样)后台,检查请求数据库,并且每当添加新条目时始终启动请求)。这样您就可以异步地发出请求,并且只要将该请求添加到堆栈就可以退出。

另外正如meouw所说,客户端不是你用php做的任何通信的一部分。 Php是一种服务器端语言,所以当客户端请求一个网页(php文件)时,服务器执行该文件(并且所有请求php文件的状态)然后将结果返回给客户端。

答案 1 :(得分:13)

这里:

ob_end_clean();
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
header("Content-Length: 1");
ignore_user_abort(true);

和卷曲:

 curl_setopt($curl, CURLOPT_TIMEOUT_MS, 1);
 curl_setopt($curl, CURLOPT_NOSIGNAL, 1);

答案 2 :(得分:8)

如果你真的不关心你的反应,你可能最好关注exec wget命令。在其他一些答案中提到这一点,但这是一个非常简单的函数,通过这种方法发送_POST包(这是异步的,需要1-2ms):

function wget_request($url, $post_array, $check_ssl=true) {

  $cmd = "curl -X POST -H 'Content-Type: application/json'";
  $cmd.= " -d '" . json_encode($post_array) . "' '" . $url . "'";

  if (!$check_ssl){
    $cmd.= "'  --insecure"; // this can speed things up, though it's not secure
  }
  $cmd .= " > /dev/null 2>&1 &"; //just dismiss the response

  exec($cmd, $output, $exit);
  return $exit == 0;
}

致谢:功能改编自 https://segment.com/blog/how-to-make-async-requests-in-php/

答案 3 :(得分:2)

http://curl.haxx.se/mail/lib-2002-05/0090.html

  

libcurl没有异步接口。   你可以自己做   使用线程或使用   非阻塞的“多接口”即   libcurl提供。阅读多重   界面在这里:

http://curl.haxx.se/libcurl/c/libcurl-multi.html

多接口的PHP示例在这里:

http://www.phpied.com/simultaneuos-http-requests-in-php-with-curl/

答案 4 :(得分:1)

我从未尝试过这个,但将CURLOPT_TIMEOUT设置为非常低的值可能会有所帮助。试试00.1

但是,我不知道cURL和客户端将如何处理此问题,是否在建立连接时将主动取消连接,并且达到超时。你必须试试。如果你正在调用PHP脚本,也许ignore_user_abort()可以确保你的脚本以任何一种方式运行。

答案 5 :(得分:0)

正如其他人所说,当您提出http请求时,您必须等待响应。

在PHP中,您可以使用exec函数发出请求。

点击此链接:php exec command (or similar) to not wait for result

答案 6 :(得分:0)

如果您有2个PHP服务器互相通信,例如服务器1 想要将JSON数据发送到服务器2 服务器2 正在做一些繁重的工作,并在收到请求后立即终止连接。数据,因此服务器1 不必等待结果。您可以这样做:

服务器1(客户端使用JSON数据创建POST请求):

使用CURL,不要使用 file_get_contents(),因为根据我的经验, file_get_contents()无法处理连接:close HTTP标头正确,并且没有终止连接。

    $curl = curl_init('http://server2.com/');
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-type: application/json"]);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode(['some data']));

    $response = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    if ($status !== 200) {
        exit("Failed with status {$status}, response {$response}, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl));
    }
    curl_close($curl);

    echo $response;

服务器2:

使用了bubba-h57中的修改代码。

// Cause we are clever and don't want the rest of the script to be bound by a timeout.
// Set to zero so no time limit is imposed from here on out.
set_time_limit(0);
// Client disconnect should NOT abort our script execution
ignore_user_abort(true);

// Clean (erase) the output buffer and turn off output buffering
// in case there was anything up in there to begin with.
ob_end_clean();
// Turn on output buffering, because ... we just turned it off ...
// if it was on.
ob_start();
echo 'I received the data, closing connection now, bye.';
// Return the length of the output buffer
$size = ob_get_length();
// Send headers to tell the browser to close the connection
// Remember, the headers must be called prior to any actual
// input being sent via our flush(es) below.
header("Connection: close");
// Hack how to turn off mod deflate in Apache (gzip compression).
header("Content-Encoding: none");
header("Content-Length: {$size}");
// Set the HTTP response code
http_response_code(200);
// Flush (send) the output buffer and turn off output buffering
ob_end_flush();
// Flush (send) the output buffer
// This looks like overkill, but trust me. I know, you really don't need this
// unless you do need it, in which case, you will be glad you had it!
@ob_flush();
// Flush system output buffer
// I know, more over kill looking stuff, but this
// Flushes the system write buffers of PHP and whatever backend PHP is using
// (CGI, a web server, etc). This attempts to push current output all the way
// to the browser with a few caveats.
flush();

// Close current session.
session_write_close();

// Here, you can proceed with some heavy work.

echo "This won't be sent, the connection should be already closed";

答案 7 :(得分:0)

在 Laravel 中

use Illuminate\Support\Facades\Http;


...Some Code here

$prom = Http::timeout(1)->async()->post($URL_STRING, $ARRAY_DATA)->wait();

... Some more important code here

return "Request sent"; //OR whatever you need to return

这对我有用,因为我不需要总是知道回复。