2012-03-07 21 views
1

我有两个文件client.php和server.php。 客户端文件向服务器文件发送HTTP请求。服务器文件处理请求的速度非常慢,所以我只希望它能够回答客户端“确定请求是正确的,结果将通过电子邮件发送”。直接从服务器中断HTTP请求

但我不知道要使服务器关闭具有合适标头的HTTP请求并继续其工作。如果我指定1秒的超时时间,则无法知道该请求是否会被服务器接受。

那么有可能在PHP?你知不知道怎么 ?

client.php:

<?php 

$resource = curl_init(); 
curl_setopt($resource, CURLOPT_URL, 'http://localhost/server.php'); 
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($resource, CURLOPT_TIMEOUT, 30); 
curl_exec($resource); 

server.php

<?php 

header('200 OK'); 
echo 'OK the request is correct, the result will be sent by email'; 

// How to write the method below? 
send_result_to_client(); 

// Simulates a slow process 
sleep(60); 

好,我找到了解决办法。 在功能send_result_to_client有人似乎是:

function send_result_to_client() 
{ 
    $myString = '...'; 
    $size = strlen($myString); 
    header("Content-Length: $size"); 
    header('Connection: close'); 
    flush(); 
} 

回答

0

对不起,但发送Connection:closeflush()而不是解决方案 - 不可移植跨服务器或浏览器。它可能似乎是一个解决方案,因为它似乎工作时,您运行一个简单的测试。如果您有

send_result_to_client(); 
sleep(60); // simulate a job... 
mail(...); // ...ENDING with a mail message 

尝试一下,然后什么都不做,或者更糟,做任何用户都行 - 只要关闭该窗口,他看到了“你会通过电子邮件通知” - 你会发现在大多数平台上,电子邮件永远不会被发送,并且工作永远不会完成。如果已收到Connection:closeContent-Length字节

curl可以终止,但RFC 2616

HTTP/1.1 defines the "close" connection option for **the sender** to signal that the connection will be closed after completion of the response. 

但服务器没有关闭连接,而不是真的。在作业处理完成之前,需要使用die()exit()

因此,您的脚本将继续执行,直到浏览器实际关闭连接 - 此时(通常为),处理将中止。也许在某些平台上它不会,但不要指望它。

您可以尝试改善与其他黑客的情况:

set_time_limit(VERY_LONG_TIME); 
    ignore_user_abort(); 

,但它确实是一个黑客。

没有真正的便携式解决方案。通常,如Manatok所建议的,作业在其他地方排队,而队列由另一个线程异步处理。这可能是最好的解决方案。

其他可能性涉及到使用atd和at命令(或Windows下的等效命令)对作业进行排队的不同方法,也许更简单。您可以通过管道一个新的PHP脚本由atd执行打造的“作业控制”与shell_exec

shell_exec("echo 'php -q /path/to/script.php \"param1\" \"param2\" | at now"); 

(或更高效,运行“at now”与popen和写入命令来执行其stdin) 。

见例如:

https://github.com/treffynnon/PHP-at-Job-Queue-Wrapper

您也可以尝试产卵并发工作,通过popenshell_exec,但你需要从服务器进程分离,或者你会发现系统被作业可执行文件的副本占用(如果在Windows下执行此操作,则为CMD.EXE)。

请参见:

Asynchronous shell exec in PHP

1

我知道这是不是正是你问什么(不知道这是可能的),但我会被另一个线程处理的队列。请求进入服务器,它将细节添加到队列(可以在数据库中)并响应客户端。然后您可以拥有一个运行并稍后处理队列的cron。

+0

好,我找到了解决办法。我编辑了我原来的帖子。 – 2012-03-07 13:22:30

+0

aaah有道理,很好:) – Manatok 2012-03-07 13:26:24

+0

这是可能的,就像你说的。使用atd(或者Scheduler,或者周围的任何不同的端口和包装器)来做到这一点。或者另一个PHP脚本,从crontab运行。 – LSerni 2012-07-05 17:28:01