PHP:发送持久异步请求
很久以前,我已经构建了这个函数,当时看起来还可以PHP:发送持久异步请求,php,asynchronous,websocket,request,Php,Asynchronous,Websocket,Request,很久以前,我已经构建了这个函数,当时看起来还可以 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);
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.1\r\n".
"Host: " . $hostName . "\r\n".
"Connection: Close\r\n".
join("\r\n", $headers)."\r\n\r\n");
fclose($fp);
}
}
它的唯一目的是从客户端请求中触发一些脚本,而不会减慢请求本身的速度,也不需要响应。然而,我今天尝试使用这个函数来启动websocket服务器,却意外地发现它根本不是异步的。下面是启动服务器的一段代码
\MF\System::sendAsyncHTTPRequest(SITE_DOMAIN, 80, 'GET', '/battleWS/startServer/'.$battleId);
header('Location: '.SITE_URL.'/battleWS/field/'.$battleId);
如您所见,我正在启动服务器,然后立即将客户端重定向到连接到服务器的页面。显然,当客户端被重定向时,服务器脚本停止执行,这对我来说是意外的,因为我认为我正在发送一个异步请求。我可以确认这一点,因为如果我在这两行之间放置一个sleep
,我就会在日志文件中看到服务器的自动关闭倒计时。我尝试从fsockopen
切换到stream\u socket\u client
,但运气不佳。这也是服务器启动脚本的开始(使用sendAsyncHTTPRequest()
调用)
这让我更加困惑,因为gnore\u user\u abort
应该保持脚本的执行
我正在寻找一种在从原始请求重定向客户端后保持服务器运行的方法,而不使用库和框架。我相信您可以使用PHP做您想做的事情 例如,类似这样的内容:
<?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 = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);
$http->on('request', $app);
$socket->listen(1337);
$loop->run();
您可以在后台执行命令行PHP客户端来执行HTTP作业。如果在后台执行,则为异步
例如:
php此php脚本使用php Cli运行
<?php
if (!isset($argv[1]))
{
die("Arguments not given\n");
}
$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.1\r\n" .
"Host: " . $hostName . "\r\n" .
"Connection: Close\r\n" .
join("\r\n", $headers) . "\r\n\r\n");
fclose($fp);
}
}
一些细节:
> /dev/null
将标准输出(即回音、打印等)重定向到虚拟文件(其中写入的所有输出都将丢失)
将错误输出重定向到标准输出,在同一虚拟和不存在的文件中写入。例如,这样可以避免将日志记录到apache2/error.log中
&
在您的情况下,最重要的是:它将分离您对$command的执行:因此exec()将立即释放您的php代码执行,并创建预期的异步行为
echo -n \$!
将给出分离执行的PID作为响应:它将由exec()返回,并使您能够使用它(例如,将此PID放入数据库,并在一段时间后将其杀死,以避免僵尸)。哦,天哪,万分抱歉,我忘了提到我正在寻找一个无库的解决方案。客户机是否正在向网络流写入数据?服务器是否正在接收请求?您使用的是TCP还是UDP?您可以发布服务器的实现吗?我觉得您必须使用PHPCLI或cronjob来实现您的应用程序purpose@Rijndael我使用HTTP(浏览器)上的普通TCP连接。正如我所说,服务器正在接收所有内容,但一旦客户端通过标题('Location:
)从发送启动服务器的请求的页面重定向,显然这两个请求都会被终止。这没有多大意义,因为我使用了忽略用户\u中止(true)
@naventhally所以我绝对没有办法从运行中的PHP脚本发送一个单独的HTTP请求,并且使用本机代码?
2>&1
&
echo -n \$!