在 PHP 上关闭窗口后,关闭所有打开的资源


close all opened resources once the window is closed on php

>我有一个使用一些资源的对象,例如

class UseResources {
    protected $proc_open;
    public function __construct()
    {
        $this->proc_open = proc_open( ... );
    }
    public function cleanup()
    {
        proc_close($this->proc_open);
    } 
};

我试图在事件上发送 Ajax 请求.unload但这不是我想要的。

我希望能够在用户关闭窗口或浏览器或连接丢失后调用清理方法?

unload 事件在窗口关闭时触发,也会在用户刷新页面或导航到新页面(即使新页面位于您的网站中)时触发。我建议在这种情况下不要使用unload。(例如,unload更适合用于提示用户在离开表单之前保存或丢失更改之类的事情。

此外,如果您实现 javascript 解决方案,您希望 (1) 要求 javascript 使用该站点(并向禁用 JS 的人显示<noscript></noscript>元素),或者 (2) 编写代码,以便您不仅仅依赖窗口关闭/清理检测例程来释放资源。

我通常实施的执行此类操作的策略是使用 ping 进程。基本上:客户端定期向服务器发送ping,服务器在收到ping时将连接/会话的idle计数器重置为0。根据需要,每分钟左右发生一次ping。然后,长时间运行的循环线程(如果您愿意,可以使用 Session 管理器)检查是否有任何超出idle threshhold(例如 3 分钟,但由您决定)空闲的客户端,如果超出,则会释放与该连接/会话相关的资源。然后,您站点中的每个页面(如果适用)都会添加此 ping 代码,以便只要页面在浏览器中打开,客户端就会开始 ping 操作。

好处

  • 跟踪用户查看您网站的时间(对于指标很有用,尤其是与用于跟踪请求数的指标结合使用时)
  • 关闭浏览器时以及用户离开站点时关闭所有与连接相关的资源
  • 如果用户导航到您站点上的其他页面[具有ping代码],则不会清除其连接资源,因为idle计数器将在下一页上重置

缺点

  • 需要JavaScript(例如setTimeoutsetIntervalXMLHttpRequest
  • 除非您在服务器上也有类似"身份验证超时"之类的东西,否则如果用户离开打开的 Web 浏览器一段时间,客户端可能会使您的服务器(和资源)长时间保持连接(您可以通过使用备用 ping 触发器来解决此问题,例如鼠标移动、将焦点设置为表单字段、 单击、滚动等)

客户端页面的粗略示例代码:

function pingServer() {
  var req;
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
  } else {
    req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  req.onreadystatechange = function() {
    if (req.readyState == 4 && req.status == 200) {
      alert("Idle timer reset on server");
    }
  }
  var url = 'ping.php'; // call php code that will reset idle timer for this client
  req.open("GET", url, true);
  req.send();
}
var pingFrequencyMs = 5 * 1000; // ping every 5 secs
setInterval(pingServer, pingFrequencyMs);
<noscript>Sorry, JavaScript is required for this website.</noscript>

这是一个非常粗略的流程示例,您可以在服务器端使用,但在您提供更多详细信息之前,我只能推测您正在使用哪种 Web 应用程序:

服务器 Ping 例程(伪代码,可以是 PHP、ASP、JSP 等)

  1. 获取客户端连接unique ID(或会话 ID,或其他)
  2. 获取客户端idle计时器的当前值,否则默认为 0(可以从内存缓存、数据库、磁盘上的文件获取此值;您的选择)
  3. 获取max idle的系统值(超时)
  4. 将客户端idlemax idle进行比较
  5. 如果客户端idle超过max idle则结束会话(无论这意味着什么;关闭连接/特定于会话的资源等 - 在您的情况下,这意味着调用cleanup例程,但请确保它具有正确的对象上下文),否则重置idle 0