2012-03-07 3 views
1

두 개의 파일 client.php와 server.php가 있습니다. 클라이언트 파일이 서버 파일에 HTTP 요청을 보냅니다. 서버 파일은 요청을 처리하는 속도가 매우 느릴 수 있으므로 클라이언트에게 "OK 요청이 맞으면 결과가 전자 메일로 전송됩니다"라고 대답하기를 원합니다.서버에서 직접 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); 

나는 해결책을 찾아 냈다. 나는 이것이 당신이 요구하는 (확실하지 않은이 가능하다)하지만 난 다른 스레드에 의해 처리되는 큐있을 것입니다 정확히 아니라는 것을 알고

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

은 해지 할 수 있지만,

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

그러나, RFC 2616에서 서버는 정말 연결을 닫을 수 없습니다. 작업을 처리하기 전에 die() 또는 exit()이 필요합니다.

브라우저가 실제로 연결을 닫을 때까지 스크립트가 계속 실행됩니다. - 그 시점에서 (보통) 처리가 중단됩니다. 어쩌면 일부 플랫폼에서는 그렇지 않지만, 그다지 중요하지는 않습니다.

당신은 다른 해킹과 상황 개선을 시도 할 수 있습니다 :

set_time_limit(VERY_LONG_TIME); 
    ignore_user_abort(); 

을하지만 해킹, 참이다.

진정한 휴대용 솔루션이 없습니다. 일반적으로 Manatok에서 제안한 것처럼 작업은 다른 곳에서 대기하고 큐는 다른 스레드에 의해 비동기 적으로 처리됩니다. 이것은 아마도 최상의 솔루션입니다.

다른 가능성은 atd 및 at 명령 (또는 Windows에서 이에 해당하는 기능)을 사용하여 작업을 대기열에 넣는 것과 똑같은 작업을 수행하는 다른 방법 일 수도 있습니다. 당신은 atd에 의해 실행되는 새로운 PHP 스크립트 파이프하여 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

당신은 또한 popen 또는 shell_exec을 통해 동시 작업을 산란을 시도 할 수 있지만 서버 프로세스에서 분리해야하거나 시스템을 확인할 수있는 것들 :

예를 들어보기 작업 실행 파일 (Windows에서이 작업을 수행하는 경우 CMD.EXE)의 복사본으로 호깅을합니다.

은 참조 :

Asynchronous shell exec in PHP

1

:에 기능 send_result_to_client에서 보일 것이다. 요청은 서버로 들어오고 큐에 세부 정보를 추가하고 (db에있을 수 있음) 클라이언트에 응답합니다. 그런 다음 나중에 큐를 실행하고 처리하는 cron을 가질 수 있습니다.

+0

좋아, 나는 해결책을 찾아 냈다. 나는 원래의 글을 편집했다. –

+0

aaah 그 말이 의미가있어, 좋은 하나 :) – Manatok

+0

당신이 말한 것처럼 그것은 가능합니다. atd (또는 Scheduler 또는 이와 유사한 여러 포트와 래퍼 중 하나)를 사용하여 수행하십시오. 또는 crontab에서 실행중인 다른 PHP 스크립트. – LSerni