Maison  >  Article  >  développement back-end  >  Le navigateur http se déconnecte activement et PHP se déconnecte activement

Le navigateur http se déconnecte activement et PHP se déconnecte activement

不言
不言original
2018-04-26 14:41:215028parcourir

Cet article partage avec vous la déconnexion active du navigateur http et la déconnexion active de php. Les amis intéressés peuvent y jeter un œil

Résumé : La cause de l'incident est due à la rencontre habituelle lors de doutes sur le développement. Une fois, après la déconnexion active du client du navigateur, il a été constaté que le script php côté serveur était toujours en cours d'exécution, je ne savais donc pas comment arrêter le script. Une autre fois, il était nécessaire de déconnecter activement le script php, puis les scripts suivants continuaient à s'exécuter (une tâche qui prenait beaucoup de temps), c'est pourquoi ce blog a été créé.

1. Le navigateur se déconnecte activement

Sous la combinaison LAMP couramment utilisée, nous pensons que le navigateur accède à un script php, le script commence à s'exécuter, le script génère du contenu et termine son exécution, Apache En réponse à http, le navigateur reçoit la réponse http et affiche le résultat.
Considérons des situations particulières.
1. Le navigateur envoie une requête http, et PHP effectue une tâche fastidieuse (20s) (en supposant que le set_time_limit de PHP est défini sur 30s. Pendant cette période, le navigateur ne répond pas et). l'utilisateur clique sur le navigateur X, le navigateur se déconnecte activement, le script php continue-t-il de s'exécuter ?
Supposons que la tâche fastidieuse soit : calculer fib(25), la réponse du test du navigateur prend 1,15 s, chaque fois que la tâche fastidieuse est exécutée, le fichier Log est écrit une fois, la tâche fastidieuse est exécutée 10 fois, et après la cinquième exécution. A ce moment, le client se déconnecte activement et observe la situation.
Le code est le suivant :

<?phpfor ($i=0; $i < 10; $i++) { 
    fib(25);
    setLog(date(&#39;H:i:s&#39;));
}function fib($n = 3){
    if($n == 0){        return 1;
    }    if($n == 1){        return 1;
    }    return fib($n - 1) + fib($n -2);
}function setLog( $massage, $path=&#39;&#39;){
    $log_path = empty($path)?&#39;./log_&#39;.date(&#39;Y-m-d&#39;).&#39;.log&#39;:$path;    $time = date(&#39;Y-m-d H:i:s&#39;);    $error_page = &#39;http://&#39; . $_SERVER[&#39;HTTP_HOST&#39;] . $_SERVER[&#39;REQUEST_URI&#39;];
    file_put_contents($log_path, "LOG TIME:".$time.PHP_EOL, FILE_APPEND);
    file_put_contents($log_path, "LOG URL:".$error_page.PHP_EOL, FILE_APPEND);    if(is_array($massage)){        $massage = json_encode($massage);
    }
    file_put_contents($log_path, "LOG MESSAGE:".$massage.PHP_EOL.PHP_EOL, FILE_APPEND);
}?>

  Le navigateur s'est déconnecté lorsque l'exécution a atteint 5,44s.
 Le journal indique : Le script a terminé 10 cycles.
 C'est différent de ce que nous pensions auparavant ;

  2. J'ai vu qu'il était dit en ligne que PHP détermine si la connexion client est déconnectée lorsque PHP envoie du contenu au client est jugé, puis nous modifions le code du test :

<phpfor ($i=0; $i < 10; $i++) { 
    fib(25);    setLog(date(&#39;H:i:s&#39;));    echo "hello";
}

//这里省略了fib和setLog函数
?>
 Testez à nouveau et constatez que les résultats sont les mêmes que le dernier test. La raison : lorsque php envoie du contenu au client, il y a trois étapes de mise en mémoire tampon, à savoir :

  tampon php => tampon du serveur Web => tampon du navigateur
  Uniquement lorsque le tampon est plein, il sera envoyé au client. C’est en fait le principe selon lequel le back-end envoie du contenu au front-end de temps en temps. Bien entendu, vous pouvez également contrôler la sortie vers le client lorsque le tampon n'est pas plein.

   

3. Modifiez à nouveau le code de test pour que le contenu envoyé au client soit suffisamment volumineux :

<?php$re = "";for($i=0; $i < 10000; $i++){    $re .= "aa";
}for ($i=0; $i < 10; $i++) { 
    fib(25);
    setLog(date(&#39;H:i:s&#39;));    echo $re;
}//这里省略了fib和setLog函数?>
  Testez à nouveau cette fois et vous constaterez que le navigateur va redémarrer après un certain temps. J'ai reçu des réponses, au lieu de la démo précédente, qui nécessitait que le script soit entièrement exécuté avant de transmettre le contenu au client. En même temps, la connexion client est fermée à ce moment-là. Lorsque le serveur envoie à nouveau du contenu au client, il vérifiera que la connexion client a été déconnectée. À ce moment, le script cessera de s'exécuter. C'est le résultat du test que nous voulons.

  

4. Modifiez à nouveau le code de test cette fois, au lieu de sortir une grande quantité de contenu à la fois, le contenu du tampon est délibérément manipulé pour que le contenu ne soit pas suffisant. la sortie du tampon vers le client est envoyée au client à l'avance. Code de test :

for ($i=0; $i < 10; $i++) { 
    fib(25);    setLog(date(&#39;H:i:s&#39;));    echo "hello " . date(&#39;H:i:s&#39;) . "<br>";
    ob_flush();
    flush();
}
//这里省略了fib和setLog函数
Résumé :

  • En principe, le client se déconnecte activement et le script php cesse de s'exécuter

  • Mais le principe est que PHP sait comment le client se déconnecte. Ce n'est que lorsque PHP envoie du contenu au client (pas le tampon PHP, ni le tampon du serveur Web), que PHP connaîtra le client. Il cessera de fonctionner. uniquement lorsque la connexion est interrompue ;

  • Il existe deux façons pour php de transmettre le contenu au client. La première consiste à remplir le contenu dans le tampon et à l'envoyer automatiquement au client ; la seconde consiste à utiliser ob_flush, la fonction flush pour vider activement le contenu du tampon vers le client ; L'exécution du script PHP est également soumise aux paramètres internes. La limite du minuteur du script peut être configurée dans php.ini ou dans le fichier de configuration d'Apache hôte, ou définie via la fonction set_time_limt dans le script

  • Lorsque le script PHP est exécuté, le client se déconnecte activement, le script php Lorsqu'il ne s'arrête pas, il est également limité par le minuteur du script

  • Lorsque le script php définit ignore_user_abort(true); la connexion est déconnectée, php envoie le contenu au client Même si le client sait que la connexion client est déconnectée, cela n'arrêtera pas l'exécution du script

  • En interne dans PHP, l'état de la connexion est maintenu ; par le système peut être vérifié via la valeur de retour de la fonction connection_status, 0 : normal ; 1 : abandonné (déconnecté) ; 2 : timeout ; La détection d'un statut modifié nécessite également que le script PHP envoie le contenu au client pour savoir, sinon ce sera toujours 0 ;

  • De plus Il existe une fonction qui peut également détecter si la connexion client est déconnectée (connection_aborted), 0 est normal, 1 est déconnecté.

  • Un problème étrange est que lorsque la connexion client a été déconnectée et que le script php est généré deux fois, le bit d'état devient 1

  • 2. Le serveur PHP se déconnecte activement

    Pour que PHP se déconnecte activement, utilisez les champs content-length et connection dans l'en-tête de réponse http, dont les significations sont :

content-length, lorsque le client reçoit l'en-tête de réponse content-length, lorsque le corps correspondant reçoit la taille spécifiée, il se déconnectera du serveur

;

  • connection,当客户端收到响应头connection的值为close或者keep-alive,决定关闭当前tcp连接或者继续使用当前连接作下一次请求;

  • 测试发现,当只指定conetent-length的时候也能达到php主动断开连接;

  • 其实说是php主动断开连接,其实是php通知客户端主动断开的连接;

  • 示例代码:

    <?phpecho "hello world";
    
    test();for ($i=0; $i < 10; $i++) { 
        fib(25);
        setLog(date(&#39;H:i:s&#39;));
    }function test(){
        $size = ob_get_length();
        header("content-length:" . $size);    //header("connection:close");
        ob_flush();
        flush();
    }//这里省略了fib和setLog函数?>



    ba33df4ef3efea3726e09756c08771e7



    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn