本人PHP水平不高,算是新手。
因为要制作一个设备参数监控的功能,所以我用到了HTML5新的技术标准,SSE(server send event)服务器发送事件。
后台框架基于ThinkPHP,代码大致如下。class DataAction extends Action {    // 将通过前台传递的当前选择节点信息写入SESSION
    public function selectNode()
    {
        $_SESSION['nodeAttr'] = $_GET['attr'];
        $_SESSION['selectNode'] = $_GET['node'];
    }    // 数据输出函数,基于SSE
    public function stream()
    {
        header("Content-Type: text/event-stream\n");
        header('Cache-Control: no-cache');
        
        while (1)
        {
            $key = $_SESSION['selectNode'];
            $attr = $_SESSION['nodeAttr'];
            $value = D('Value');
            $paramList = $value->join("sys_deviceparam ON cfg_deviceparamvalue.DeviceParamInfoID = sys_deviceparam.DeviceParamInfoID")->where("DeviceID = '$key'")->select();
            $Paramstr = json_encode($paramList);
            echo "event:newdata\n";
            echo "data:{\042Rows\042:$Paramstr}"."\n\n";
            ob_flush();  
            flush();  
            sleep(1); 
        }
    }
}
前台代码如下//建立SSE对象
source = new EventSource("__APP__/Data/stream");
source.addEventListener("newdata",function(event)
{
    gdata = event.data;
    gdata = JSON.parse(gdata);    // gridManager是我的前端控件,这里可以不关注
    gridManager.set({data : gdata});
    gridManager.loadData();
})现在已经能达到我想要的结果,后台会实时推送新鲜的数据到前台。
不过还有一个新的问题,就是用户会切换显示的设备。
我之前的思路是,用户在切换设备时,通过一个GET向后台发送设备的ID信息,再有后台的selectNode方法写入SESSION。
而结果并不尽如人意。当前台触发改写SESSION的GET时,因为EventListener一直在抓去数据,所以会造成HTTP的阻塞,也就是说GET一直发不出去(或者是发出去但是没响应吧。。)。
当时想,会不会是因为SESSION被锁死,便用了session_write_close(),结果HTTP不阻塞了,但是SESSION中相关的字段还是没有被改写。。所以请教各位有没有相关的经验,或者有更好的解决思路?不胜感激

解决方案 »

  1.   

    每当前台发起一个新连接时,就将在服务端产生一个新的 sessionid。所以通过session传递数据的设想是不能实现的,必须另辟蹊径
      

  2.   


    感谢版主的回复。
    我现在想的思路是,在每次用户切换设备的事件发生时,先关闭EventListener,然后在回调函数里重新执行EventListener。
    不知道版主有没有什么更好的解决思路呢?
      

  3.   

    如果是关闭EventListener,那么就失去 SSE 的意义,而是退化成普通 ajax 轮询了
    你可以通过文件、数据库、共享内存等手段保存来自客户端的信息。
    在 stream() 的“死循环”中检查是否有新的客户端指令(就像你检查session那样)
    另外还应加上退出循环的指令