使用服务器推送事件和PHP会话管理技术

3
我在项目中使用服务器推送事件技术,在JS调用PHP页面时,比如说 eventserver.php ,基本上是一个无限循环,它会检查 $_SESSION 变量中是否存在事件。 在我的第一次实现中,这导致我的网站挂起,因为事件服务器锁定了会话,并且直到超时才释放。然而,我通过在循环中连续使用 session_write_lock()session_start() 来解决了这个问题。
这实际上会引起很多PHP警告(在Apache error.log中),显示“无法发送会话缓存限制器——头已经被发送”,“无法发送会话cookie”等等。
这里发布一些代码。
session_start();

header('Cache-Control: no-cache');
header('Content-Type: text/event-stream');

class EventServer
{        

    public function WaitForEvents( $eventType )
    {   
        // ... do stuff

        while( true )
        {
            // lock the session to this instance
            session_start();

            // ...check/output the event

            ob_flush();
            flush();

            // unlock the session 
            session_write_close();
            sleep( 1 );
        }          
    }
}

为什么会发生这种情况?

当然,你在提问之前已经很认真地谷歌搜索了“无法发送会话缓存限制器 - 标头已发送”这个问题,是吗? - Denis de Bernardy
3
使用系统的CRON而不是循环脚本会更好,您同意吗? - Gadoma
1
对于客户端的事件常量轮询,您可能需要研究Ajax。 (还有一种称为“长轮询”的技术,但据我所知,它与香草PHP不兼容 - 如何实现Comet?) - Pekka
当然,我已经搜索了答案,但我的情况有点不同。顺便说一下,我已经尝试过ajax/长轮询,但没有达到我需要的结果。据我所知,服务器发送事件(或WebSockets,但我只需要“单向”通信)是实现我的需求的最佳技术。 - Socket2104
4个回答

1
我正在做与OP相同的事情,并遇到了同样的问题。其中一些答案不理解eventSource应该如何工作。我的代码与你的完全相同,使用一个会话变量来知道用户所在的视图,从而驱动在服务器触发时返回的数据。它是实时协作应用程序的一部分。
我只需在session_start()前面添加一个@来抑制日志中的警告。这不是真正的修复,但它可以防止日志填满。
或者,不确定它对您的应用程序是否有效,但您可以使用ajax将要监视的会话变量写入数据库,然后您的eventSource脚本可以监视DB中的更改,而无需启动会话。

0

可能是因为您在代码中启动了两次会话。不要在循环开始时重新启动会话,而是在sleep()之后重新启动。


0

使用SSE时不需要无限循环。EventSource会保持与服务器的开放连接,服务器端数据的任何更新都将被客户端读取。

在此处查看SSE的基本用法


0

这不是一个好主意。HTTP是一种请求-响应协议,因此如果您希望服务器-客户端通信是双向的,您需要研究Websockets或类似的东西。还有像“长轮询”和“心跳”之类的东西。

如果您想要一个事件循环,请尝试使用Apache Tomcat中的Servlets。

由于设计问题,您将花费数小时来解决问题。

如果您只想从JavaScript发送消息到PHP,请查看Ajax。

确保您了解正在使用的技术栈的概述:)


我可能没有最好地解释我的情况:我不需要“双向”通信,而只需要服务器->客户端的通信。 FYI,我已经在使用ajax来异步与服务器端通信。 - Socket2104
为什么会出现无限循环? - ddoor
每当服务器通知事件发生时,循环内的代码会读取它并通知正在监听的客户端JS。据我所知,使用SSE没有其他方法可以实现这一点。 - Socket2104
就像我之前说的,HTTP是一种请求-响应协议。客户端发出请求,服务器发送响应。如果您想让服务器向客户端推送异步数据,则需要双向通信。否则,您必须等待客户端发出请求以提供“通知”数据。您可以尝试设置客户端以轮询服务器,这更有意义。 - ddoor
2
我正在设置一个JS,其中包含“var source = new EventSource('eventserver.php');”的onload事件,然后附加一些监听器,如“source.addEventListener('event',callback())”。这不是HTTP请求:) EventSource使用流。 - Socket2104
1
@Socket2104 这个人显然从来没有听说过SSE的。 - Shawn31313

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接