2013-04-13 8 views
3

에서 중단 : http://www.php.net/manual/en/features.connection-handling.php http://www.php.net/manual/en/function.register-shutdown-function.phpPHP가 검색하지 않는 연결은 내가 읽고 깊이 이러한 이해 한 모든

을하지만, 내가 거기에 설명 된대로 작동하지 않는 PHP 5.1.6 및 5.3과 일 모두를 테스트했습니다. 내가 관찰 한 것은 다음과 같다 :

  • connection_status()는 클라이언트가 연결을 닫은 후에도 항상 true를 반환한다.
  • ignore_user_abort가 0 인 경우에도 클라이언트가 연결을 닫은 후에도 스크립트 실행이 계속됩니다.
  • register_shutdown_function()으로 등록 된 함수는 스크립트가 끝날 때까지 실행되지 않습니다. 클라이언트가 연결을 중단하면 스크립트가 중단되지 않습니다 (따라서 함수가 호출되지 않습니다).

기본적으로 PHP는 클라이언트의 연결 끊김을 모두 감지하지 않습니다.

ignore_user_abort가 1로 설정된 것과 같지 않습니다.이 경우 스크립트가 계속 실행되고 종료 될 때까지 shutdown 함수가 호출되지 않더라도 connection_status()는 1을 반환합니다. 그건 사실이 아니야.

ini_get ("ignore_user_abort")는 예상대로 0을 반환합니다.

이것은 PHP의 버그입니까? 아니면 아파치 설정에 의한 것일 수 있습니까?

위의 설명서에서 설명한대로 PHP를 작동 시키려면 어떻게합니까?

테스트 스크립트 :

<?php 

function myShutdown() { 
    error_log("myShutdown ".connection_status()." ".ini_get("ignore_user_abort")); 
} 

register_shutdown_function(myShutdown); 

echo "Hi!"; 
error_log(" *** test/test *** "); 
for ($i=0; $i<10; $i++) { 
    sleep(1); 
    error_log("."); 
    echo "."; 
} 
?> 

단계 재현 : 를 - 스크립트 의 URL을 방문 - 십초이 경과하기 전에 클라이언트의 연결을 중단

(예 : 브라우저에서 정지 버튼을 누르십시오)

예상/원하는 동작 : 로그 미만 10 점을 표시해야하고, 결국 "myShutdown 1 0"에서 (실시간으로 로그를 볼 경우 myShutDown 즉시 나타납니다 때 클라이언트의 연결을 끊)

관찰 된/현재 동작 : 로그는 항상 정확히 10 도트를 표시하고 끝에 "myShutdown 0 0"을 표시합니다 (실시간으로 볼 경우 클라이언트가 연결을 끊어도 상관없이 10 초 동안 계속됩니다).

+1

왜 'PHP'버전을 더 이상 지원하지 않습니까? – Baba

+0

PHP를 아파치 모듈로 실행하고 있습니까? – hek2mgl

+0

@ hek2mgl 예, 아파치 모듈로 – matteo

답변

5

처음에는 기본 우분투 12.04 램프 설치 (php5.3)를 사용하여 작동하지 못했습니다. 그러나 나는 약간의 정보와 희망이 도움이된다. 모든 의견이나 편집을 부탁드립니다! :)


코드에 두 가지 문제점이 있습니다. 첫 번째 문법 오류입니다. register_shutdown_function()을 호출 할 때 myShutdown 주위에 작은 따옴표가 누락되었습니다.

register_shutdown_function('myShutdown'); 

내가 echo의 후 누락 된 flush() 호출이 볼 수있는 두 번째 문제 : 라인에 변경합니다.설명서의 내용 :

PHP는 클라이언트에 정보를 보내려고 시도 할 때까지 사용자가 연결을 중단했다는 것을 감지하지 못합니다. echo 문을 사용한다고해서 정보가 전송되는 것을 보장하는 것은 아닙니다. flush()를 참조하십시오.

심지어 어떤 경우에도 flush()은 도움이되지 않습니다. flush()의 문서에서 :

플러시() 웹 서버의 버퍼링 방식을 재정의 할 수 없습니다 그것은 브라우저에서 모든 클라이언트 측 버퍼링에 영향을주지 않습니다. 또한 PHP의 사용자 공간 출력 버퍼링 메커니즘에도 영향을 미치지 않습니다. 즉, ob 출력 버퍼를 사용하는 경우 ob_flush() 및 flush()를 호출하여 ob 출력 버퍼를 플러시해야합니다.

특히 Win32에서 여러 서버는 결과를 브라우저에 전송하기 전에 종료 될 때까지 스크립트의 출력을 버퍼링합니다.

mod_gzip과 같은 Apache 용 서버 모듈은 flush()가 클라이언트에 즉시 데이터를 보내지 않도록하기 위해 mod_gzip과 같은 버퍼링을 자체적으로 수행 할 수 있습니다.

심지어 브라우저는 표시하기 전에 입력을 버퍼링 할 수 있습니다. 예를 들어 Netscape는 행의 끝이나 태그의 시작을 수신 할 때까지 텍스트를 버퍼링하고 가장 바깥 쪽 테이블의 태그가 표시 될 때까지 테이블을 렌더링하지 않습니다.

일부 버전의 Microsoft Internet Explorer는 256 바이트 출력을받은 후에 페이지를 표시하기 시작하므로 플러시하기 전에 여분의 공백을 보내야 해당 브라우저에 페이지가 표시됩니다.

apache_setenv('no-gzip', 1); 
ini_set('zlib.output_compression', 0); 
ini_set('implicit_flush', 1); 

그러나, 이것은 나를 위해 작동하지 않았다 다음 해당 페이지의 코멘트에

여러 헤더와 아파치 CONFIGS을 설정할 수있는 조언이있다. 웹 서버가 0.0037 초 후에 내용 ('안녕')을 보내지 만 wiresharek를 사용하여 이것을 조사했습니다. 웹 브라우저가 페이지를 버퍼링했습니다.

+0

누락 된 작은 따옴표에 대한 부분을 제거해야합니다. rehister_shutdown_function()은 호출 가능을 허용하고 함수는 호출 가능합니다. 그렇지 않다면 오류 btw가 발생합니다. – matteo

+2

'Notice : 정의되지 않은 상수 myShutdown 사용 - 'myShutdown'in ...'을 사용합니다. 'error_reporting' 레벨을 올려야합니다. – hek2mgl

+0

보세요! 출력 버퍼링이 문제 여야합니다. 나는 gzipping이 꺼져 있어도 PHP의 암시 적 플러시에 관계없이 아파치 버퍼링을한다고 생각한다. 아마 시도한 해결 방법조차도 작동하지 않는 이유 일 것이다. – matteo