https://segmentfault.com/q/1010000000191102

首先 ... session_destory() 是一个函数 ...

这个函数在任何情况下都不会被 php 引擎自动调用 ... 只能你手工去调用 ...

php 内部存在着清理 session 的机制 ... 但与这个函数完全无关 ...

如果你想问的是什么时候该手工调用这个函数 ...答案就是在你想完全清理掉当前 session 的时候 ...

问题里面提及的几种情况 ... 不管是关闭网页也好 ... 关闭浏览器也罢 ... 甚至你把浏览器删掉重装了 ...

都不会影响到已经生成的 session ... 一言以蔽之 ... 所有浏览器行为都不会导致 session 被自动销毁 ...

那么 ... php 到底是如何清理 session 的呢 ..?

仔细去读 php.ini ... 你可以发现如下几行 ...

; Defines the probability that the 'garbage collection' process is started
; on every session initialization. The probability is calculated by using ; gc_probability/gc_divisor. Where session.gc_probability is the numerator ; and gc_divisor is the denominator in the equation. Setting this value to 1 ; when the session.gc_divisor value is 100 will give you approximately a 1% ; chance the gc will run on any give request. ; Default Value: 1 ; Development Value: 1 ; Production Value: 1 ; http://php.net/session.gc-probability session.gc_probability = 1 ; Defines the probability that the 'garbage collection' process is started ; on every session initialization. The probability is calculated by using ; the following equation: gc_probability/gc_divisor. Where session.gc_probability ; is the numerator and session.gc_divisor is the denominator in the equation. ; Setting this value to 1 when the session.gc_divisor value is 100 will give you ; approximately a 1% chance the gc will run on any give request. Increasing this ; value to 1000 will give you a 0.1% chance the gc will run on any give request. ; For high volume production servers, this is a more efficient approach. ; Default Value: 100 ; Development Value: 1000 ; Production Value: 1000 ; http://php.net/session.gc-divisor session.gc_divisor = 1000 ; After this number of seconds, stored data will be seen as 'garbage' and ; cleaned up by the garbage collection process. ; http://php.net/session.gc-maxlifetime session.gc_maxlifetime = 1440 

其实英文的注释已经说得很明白了 ... 但如果你不想看 ... 我也可以解释给你听 ...

由于 php 的工作机制 ... 它本身不会提供 daemon 来定时扫描 session 信息并判断其是否失效 ...

当你每次调用 session_start() 时 ...

php 会根据 session.gc_probability 和 session.gc_divisor 来决定是否启用 Garbage Collector ...

Garbage Collector 顾名思义 ... 被叫做 垃圾回收器 ... 也就是俗称的 GC ...

具体一些讲 ... 在我刚刚贴的配置文件里 ...

session.gc_probability = 1
session.gc_divisor = 1000

就是说 php 会有千分之一的概率会启动垃圾回收 ...

而垃圾回收的工作就是在 session 存储路径 session.save_path 下扫描所有存在的 session ...

然后用当前时间减去每个 session 的最后修改时间再跟 session.gc_maxlifetime 参数进行比较 ...

如果某个 session 的生存时间超过了 session.gc_maxlifetime 的设定值就把它销毁掉 ...

事实上这个过程完全是 php 引擎的行为 ... 和你的程序无关 ... 和用户做了什么也无关 ...

用户关闭浏览器再开 ... 因为 cookie 失效他会获得一个新的 session ...

但这并不代表他原来的 session 就被销毁了 ... 那个 session 依然在服务器上存在 ...

如果他手动把名字等于 session.name 的那个 cookie 的值改回之前的 session_id() ...

还是可以重新获得之前的那个 session 的 ...

另外一种情况 ... 如果一个用户获得 session 之后长时间没有任何动作 ...

他就可能因为其他用户触发了垃圾回收而丢失掉自己的 session ...

大体来说就是如此 ... 更加细节的东西 ... 你可以参考 php 手册上 关于垃圾回收的章节 ...

恩 ... 就是这样啦 ...

//-------------------------------------------------------------------------------

深入理解session过期机制

首先得明白:session的过期时间由两方面决定的; 
1存储在客户端的$_COOKIE['PHPSESSID']的过期时间(默认cookie名称为PHPSESSID,可通过php.ini中的session.name修改。) 
2.存储在服务器端的相对应的session文件(session文件名和上述cookie的值一一对应),默认为1440秒,即24分钟

ok,现在详细阐述上述两者的关系: 当执行session_start()的时候,其实是做了两件事: 1,检查客户端发送过来的的所有cookie(当然也包括$_COOKIE['PHPSESSID'], 如果有的话),根据$_COOKIE['PHPSESSID']的值(这是由apache产生的随机字符串,如0lkbd2se458r600m2m7o1r4ic5)来访问 相对应的 session文件(如:sess_0lkbd2se458r600m2m7o1r4ic5,我的默认存储在‘E:\wamp\tmp’下),这两者是一 一对应的关系。打个比喻:$_COOKIE['PHPSESSID']就是一把开启宝盒的钥匙,而那个宝盒就是session文件,里面存储着用户的重要 信息,也就是session的值, 如:$_SESSION['uid']=1,$_SESSION['username']='name',$_SESSION['pwd']='pwd', 当然文件里面的值是经过序列化的。 2,如果客户端没有传来$_COOKIE['PHPSESSID'],就会有服务端产生一个随机的$_COOKIE['PHPSESSID']并存储在客户端。

明白上面这些,我们可以通过下面的方法修改session的过期时间: 
1.session_set_cookie_params('50');//修改$_COOKIE['PHPSESSID'],的生存时间为50秒

(或者可以这样: setcookie(session_name(),session_id(),time()+50);)

2.ini_set('session.gc_maxlifetime','50');//设置session文件的有效时间为50秒

但是,可能有些朋友会做这样 一个试验, 在50秒内获取$_COOKIE['PHPSESSID']的值并记录下来(如黑客截获这个cookie),这样等50秒过后发现原先 的$_COOKIE['PHPSESSID']值确实不存在了,而出现了一个新的$_COOKIE['PHPSESSID'],但是‘E:\wamp \tmp’下的旧session文件却没有消失(默认只有1/1000的概率会消失,应该不会碰到吧,呵呵),这是为什么呢?我不是已经设置了.ini_set('session.gc_maxlifetime','50');了 吗?再做一个实验:这时你伪造一个$_COOKIE['PHPSESSID'],值为刚才你记录下的,神奇的事发生了,你依然可以访问刚才旧的 session文件!!!(虽然他已经过期),只要这个文件没被删除,用相对应得$_COOKIE['PHPSESSID']依然可以进行访问!!!

那我们设置ini_set('session.gc_maxlifetime', '50');还有什么意义呢?这就涉及的GC(GarbageCollector)的回收机制。 
默 认情况下,session.gc_probability = 1,session.gc_divisor=1000,也就是说有1/1000的可能性会启动GC。GC的工作,就是扫描所有的session信息,用当 前时间减去session的最后修改时间(modifieddate),同session.gc_maxlifetime参数进行比较,如果生存时间已经 超过gc_maxlifetime,就把该session删除。只要没有启动GC,即使session过期,也仍旧可通过相对应 得$_COOKIE['PHPSESSID']进行访问! 
   
原文参考: http://www.jb51.net/article/26890.htm 
                 http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2012/0621/10583.html

转载于:https://www.cnblogs.com/jukan/p/5431384.html

什么情况下会调用到session_destroy()相关推荐

  1. 通过Xvfb实现无显示器情况下调用浏览器

    今天要记录的是通过Xvfb实现无显示器情况下调用浏览器,实现浏览器视频功能. 问题是这样的,最近我在学openVidu的相关技术,测试类中有通过浏览器去调取视频的相关代码,在windows操作系统下能 ...

  2. 设置失败重新发起_微服务架构下请求调用失败了怎么办!

    微服务架构相比单体架构,服务的调用从同一台机器内部的本地调用变成了不同机器之间的远程方法调用,但是这个过程也引入了两个不确定的因素: - 调用的执行是在服务提供者一端,即使服务消费者本身是正常的,服务 ...

  3. rtsp协议_如何在RTSP协议视频智能平台EasyNVR未登录的情况下调用通道直播的接口?...

    原标题:如何在RTSP协议视频智能平台EasyNVR未登录的情况下调用通道直播的接口? TSINGSEE青犀视频云边端架构全线都提供了丰富的API接口,用户可以自由调用进行二次开发.在本文之前,我们博 ...

  4. C语言什么时候必须用到二级指针?(需要调用函数为一维空指针确定值的情况下,需要传入二维指针,也就是那个一维指针的指针)

    结论:需要调用函数为一维空指针确定值的情况下,需要传入二维指针,也就是那个一维指针的指针 例子:为空指针p开辟内存空间 1.不用二级指针(无法实现) #include <stdio.h> ...

  5. c#中跨线程调用windows窗体控件 .我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。...

    首先来看传统方法: public partial class Form1 : Form{public Form1() { InitializeComponent(); } private void F ...

  6. 继承情况下构造方法的调用过程-java

    继承情况下构造方法的调用过程-java super关键字:可以看做是直接父类对象的引用.每个子类对象都会有一个super引用 指向其直接父类对象.super可以:1.调用成员变量 super.colo ...

  7. 【Servlet】什么情况下调用doGet和doPost

    ⭐什么情况下调用doGet()和doPost()? 默认情况是调用doGet()方法,JSP页面中的Form表单的method属性设置为post的时候,调用的为doPost()方法:为get的时候,调 ...

  8. 没有lib文件的情况下,怎么隐式调用dll

    有时候,总会遇到只有一个dll没有头文件,也没有lib文件的情况下,怎么隐式调用呢? 1.首先要生成lib文件,方法如下: Visual C++ 开发工具提供了两个命令行工具,一个是dumpbin.e ...

  9. 接口调用简单、多平台支持的RTSP-Server组件EasyRTSPServer如何修正多网卡多IP情况下解码器不能解码显示问题

    EasyRTSPServer修正多网卡多IP情况下解码器不能解码显示问题 提出问题: 海康NVR接入正常,但接入海康解码器出不来图像. 分析问题: 海康解码器是以rtp over udp的方式进行取流 ...

最新文章

  1. 免费的XShell替代品,同时支持Windows,macOS,Linux!又来一款国产良心工具....
  2. CCBPM工作流引擎的消息机制与设计
  3. mysql 存储过程基础_MySQL基础-存储过程
  4. centos java程序_刚得到一台centos7服务器,作为Java程序员应该做的事
  5. 【数据结构与算法】之容器盛最多水的算法实现
  6. Oracle学习(十五)PLSQL安装
  7. dreamweaver翻译器没有被装载由于错误coldfusion.htm有不正确的设置信息
  8. JAVA并行框架:Fork/Join
  9. c#中contextMenuStrip与datagridview使用CellMouseDown事件及treeview使用mousedown事件
  10. ERROR (ClientException): Unexpected API Error
  11. python更新数据库表的时间字段_python更新数据库中某个字段的数据(方法详解)
  12. C++ 容器适配器(stack、queue、priority_queue)
  13. java 声明是否合法,一个合法的Java源程序中定义了4个类,其中属性为public的类可能有( )个...
  14. 用ps制作LOGO(个人向)
  15. SQL连接查询语句(内、外、交叉和合并查询)
  16. PPT文字怎样做断开效果和穿透效果
  17. Webpack:We noticed you‘re using the `useBuiltIns` option without declaring a core-js version.
  18. 爱加密Android APk 原理解析
  19. *基于类平衡自我训练的无监督域自适应用于语义分割
  20. mac上安装R和RStudio

热门文章

  1. Linux命令修复方法,在Linux终端运行sudoedit -s /命令看未修复和已修复的效果
  2. 【sklearn学习】随机森林分类、回归
  3. java有password_hash吗,java 实现 PHP password_hash() password_verify() 单向验证
  4. mysql 当前排名查询,MySQL排名查询分配
  5. python都有什么包_常用的Python包有哪些,如何快速掌握Python编程
  6. 如何破解Synplify Pro 9.6.2? (SOC) (Synplify)
  7. Hough变换的基本思想
  8. 如何直接强制客户端刷新.js文件
  9. 【人体姿态估计2】Real-time Multi-person 2d pose estimation using part affinity fields_2017
  10. TensorFlow(六)with语句