PHP:发送持久异步请求



很久以前,我已经构建了这个函数,在当时

public static function sendAsyncHTTPRequest($hostName, $port = 80, $method, $uri, $headers = array()){
    $fp = fsockopen($hostName, $port, $errno, $errstr, 30);
    if (!$fp) {
        throw new Exception($errstr, $errno);
    } else {
        fwrite($fp, "$method $uri HTTP/1.1rn".
                    "Host: " . $hostName . "rn".
                    "Connection: Closern".
                    join("rn", $headers)."rnrn");
        fclose($fp);
    }
}

的唯一目的是从客户端请求触发一些脚本,而不减慢请求本身的速度,也不期望得到响应。然而,我今天试着使用这个功能,启动一个websocket服务器,惊讶地发现它根本不是异步的。下面这段代码应该用来启动服务器

MFSystem::sendAsyncHTTPRequest(SITE_DOMAIN, 80, 'GET', '/battleWS/startServer/'.$battleId);
header('Location: '.SITE_URL.'/battleWS/field/'.$battleId);

如您所见,我正在启动服务器,然后立即将客户端重定向到连接到服务器的页面。显然,当客户端被重定向时,服务器脚本停止执行,这对我来说是意外的,因为我相信我正在发送异步请求。我可以确认这一点,因为如果我在这两行之间放入一个sleep,我开始在日志文件中看到服务器的自动关机倒计时。我试着从fsockopen切换到stream_socket_client,没有运气。这也是服务器启动脚本的开始(用sendAsyncHTTPRequest()调用)

set_time_limit(0);
ignore_user_abort(true);

这更让我困惑,因为ìgnore_user_abort应该保持脚本执行。

我正在寻找一种方法来保持服务器运行重定向客户端从原始请求后,不使用库和框架。

您可以在后台执行命令行PHP客户端来执行HTTP任务。如果在后台执行,则为异步。

的例子:

process.php此PHP脚本使用PHP命令行运行。

<?php
if (!isset($argv[1]))
{
   die("Arguments not givenn");
}
$args = json_decode($argv[1]);
list($hostName, $port, $method, $uri, $headers) = $args;
sendAsyncHTTPRequest($hostName, $port, $method, $uri, $headers);

function sendAsyncHTTPRequest($hostName, $port, $method, $uri, $headers = array ())
{
   $fp = fsockopen($hostName, $port, $errno, $errstr, 30);
   if (!$fp)
   {
      // as your code is asynchronous, no way to catch this exception
      throw new Exception($errstr, $errno);
   }
   else
   {
      fwrite($fp,
         "$method $uri HTTP/1.1rn" .
         "Host: " . $hostName . "rn" .
         "Connection: Closern" .
         join("rn", $headers) . "rnrn");
      fclose($fp);
   }
}

execute.php此代码由apache执行(当前执行sendAsyncHTTPRequest方法)。

$escaped_script = escapeshellarg(__DIR__ . '/process.php');
$escaped_args = escapeshellarg(json_encode(array($hostName, $port, $method, $uri, $headers)));
exec("/usr/bin/php {$escaped_script} {$escaped_args} > /dev/null 2>&1 & echo -n $!");

一些细节:

> /dev/null

将重定向标准输出(例如:你的echo, print等)到一个虚拟文件(写入其中的所有输出都会丢失)。

2>&1

将错误输出重定向到标准输出,写入同一个虚拟且不存在的文件。这样可以避免在apache2/error.log中写入日志。

&

在你的情况下是最重要的:它将分离你的$command执行:所以exec()将立即释放你的PHP代码执行,并创建预期的异步行为。

echo -n $!

将给出您分离执行的PID作为响应:它将由exec()返回,并使您能够使用它(例如,将此PID放入数据库并在一段时间后杀死它以避免僵尸)。

我相信你可以用ReactPHP做你想做的事

https://github.com/reactphp/react

例如:

<?php
$i = 0;
$app = function ($request, $response) use (&$i) {
    $i++;
    $text = "This is request number $i.n";
    $headers = array('Location:' => 'http://domain.com');
    $response->writeHead(200, $headers);
    $response->end($text);
};
$loop = ReactEventLoopFactory::create();
$socket = new ReactSocketServer($loop);
$http = new ReactHttpServer($socket);
$http->on('request', $app);
$socket->listen(1337);
$loop->run();

相关内容

  • 没有找到相关文章

最新更新