• 技术文章 >后端开发 >php教程

    http 浏览器主动断开连接 与 php主动断开连接

    不言不言2018-04-26 14:41:21原创2713

    本篇文章给大家分享了http 浏览器主动断开连接 与 php主动断开连接,有兴趣的朋友可以看一看

    摘要:事件起因是因为平时在开发中遇到的疑惑。一次是浏览器客户端主动断开了连接后,发现服务器端的php脚本还在执行,以至于不知道怎样让脚本停下来。还有一次是有需求让php脚本主动断开连接,然后后续脚本继续执行(一个耗时任务),所以有了这篇博客。

    一、浏览器主动断开连接

      在常用的LAMP组合下,我们认为,浏览器访问一个php脚本,脚本开始执行,脚本输出内容,并结束运行,apache响应http,浏览器收到http响应,显示结果。
      下来考虑下特殊的情况。
      1、浏览器发送http请求,php执行了一个耗时任务(20s)(假设php的set_time_limit设置的是30s),在此期间浏览器无响应,用户点击浏览器X,浏览器主动断开连接,php脚本是否还继续运行。
      假设耗时任务是:计算fib(25),浏览器测试响应需要时间1.15s,每执行一次耗时任务,写文件Log写一次,执行10次耗时任务,在执行第5次的时候,客户端主动断开连接,观察情况。
    代码如下:

    <?phpfor ($i=0; $i < 10; $i++) { 
        fib(25);
        setLog(date('H:i:s'));
    }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=''){
        $log_path = empty($path)?'./log_'.date('Y-m-d').'.log':$path;    $time = date('Y-m-d H:i:s');    $error_page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        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);
    }?>

      浏览器在执行到5.44s的时候断开了连接。
      日志显示:脚本执行完了10次循环。
      这与我们之前认为的不一样;

      2、优化一下,看到网上说,php判断客户端连接是否断开,是在php往客户端输出内容的时候判断的,那么我们把测试代码修改一下:

    <phpfor ($i=0; $i < 10; $i++) { 
        fib(25);    setLog(date('H:i:s'));    echo "hello";
    }
    
    //这里省略了fib和setLog函数
    ?>

      再次测试一下,发现和上一次的测试结果是一样的。究其原因:php往客户端输出内容的时候,要有3个缓冲阶段,分别是:
      php buffer => web server buffer => browser buffer
      只有当缓冲区满了的时候才会输出到客户端,这其实就是,后端每隔一段时间输出内容到前端的原理。当然也是可以控制当缓冲区没有满的时候,也让输出到客户端。

      3、再修改测试代码,让输出客户端的内容足够大:

    <?php$re = "";for($i=0; $i < 10000; $i++){    $re .= "aa";
    }for ($i=0; $i < 10; $i++) { 
        fib(25);
        setLog(date('H:i:s'));    echo $re;
    }//这里省略了fib和setLog函数?>

      这次再测试,就会发现浏览器会隔一段时间就收到一些相应,而不是之前的demo,需要脚本完全执行完才输出内容到客户端。同时,这个时候关闭客户端连接,服务器端当再次向客户端输出内容的时候,就会检查客户端连接已经断开了,这个时候脚本就会停止运行了。这是我们想要的测试结果。

      4、再修改测试代码,这次不让一次输出一个很大的内容,而是有意操作缓冲区内容,让虽然不够从缓冲区输出到客户端的内容提前输出到客户端。
    测试代码:

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

    小结:

    二、php服务器端主动断开连接

      要让php主动断开连接,要使用http响应头里面的content-length和connection两个字段,意义分别为:

    示例代码:

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



    <完>

    以上就是http 浏览器主动断开连接 与 php主动断开连接的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:Firefox webkit http
    上一篇:php7.0 + phalcon 安装配置 下一篇:使用Socket发送邮件
    线上培训班

    相关文章推荐

    • 你知道这个PHP命令行选项解析库(pflag)吗?• 带你看懂PHP中的class定义类与成员属性方法• PHP中如何才能将时间日期格式化?怎么计算时间差?• 最详细的教你PHP时间戳与日期时间的转换• 一定搞得懂PHP中如何添加图片水印

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网