2015-06-16 42 views
1

我想实现一个服务器发送事件,服务器将发送客户端新消息。如何在没有警告/错误的循环中使用session_start()?

这里的挑战是服务器更新会话,然后回显他们的内容。

问题是我需要在一个无限循环中有这个问题。

这是我所做的。

while(true){ 


     session_start(); 
     header("Content-Type: text/event-stream" . PHP_EOL); 
     header("Cache-Control: no-cache" . PHP_EOL); 

     //configure the connection 
     $conf = new ICWS\Config\Config($url, $stationName); 

     //create a new instance of icws 
     $attrebutes = array('AccoRDI_mid','AccoRDI_account_id'); 
     $icws = new ICWS\Connection($conf, $attrebutes, true); 

     $messaging = new ICWS\Messaging($icws); 

     $messaging->processMessages(); 
     session_write_close(); 

     $result = $messaging->getCallsQueue(); 

     echo 'event: getMessagingQueue' . PHP_EOL; 
     echo 'data: ' . json_encode($result) . PHP_EOL;  

     ob_end_flush(); 
     flush(); 

     usleep($sleepTime * 1000000); 
    } 

这里的问题是,我得到以下警告/通知

Warning: session_start(): Cannot send session cache limiter - headers already sent and 

Notice: ob_end_flush(): failed to delete and flush buffer. No buffer to delete or flush i 

我需要的session_start()在循环的原因是因为我需要看完后,立即解开了会议文件在脚本睡觉之前。 的想法是

  1. 开始/恢复会话
  2. 更新会话值
  3. 显示会话的内容
  4. 解锁/释放会话,允许其他进程使用它
  5. 返回到第1步

我该怎么做才能避免这里的错误?

+0

你不能在5秒内使用cron任务吗? –

+0

“我如何在没有警告/错误的循环中使用session_start()?”你不能 –

+0

我需要实现服务器发送的事件这里是关于我在做什么的更多信息http://stackoverflow.com/questions/30873956/server-sent-events-polling-causing-long-delays – Jaylen

回答

1

在您的具体情况...我会做没有会话。一个会话只是一个序列化的对象到一个临时(很好,垃圾回收)的文件中。谁来阻止你编写自己的备用会话处理程序?

在其最基本的形式,撇开错误检查和恢复,这有点像

function getAlternateSessionData() { 
    $raw = file_get_contents(getAlternateSessionFileName()); 
    return unserialize($raw); 
} 

file_put_contents()同样保存会话。您必须考虑如何防止两个不同的服务器进程对同一个会话文件的并发访问。但是您只能在开始时发送会话ID cookie,因此从不实际“重新启动”会话。

另一种可能性是实现使用内存的替换会话 - 如果服务器进程不终止 - 或者类似的Redis(你可以做到这一点与普通的会议太多,但那些将发送会话缓存限制器)。

您也可以使用session_set_save_handler()覆盖PHP自带的函数的文件读写功能,使所有的会话处理(cookies等)保持不变。通过处理会话文件管理,您可以随时提交会话。 尽管它们与PHP自己的会话处理程序兼容(如果它们不是,您将不得不在每个脚本访问中包含会话处理程序),但您仍需要仔细考虑如何与并发访问会话文件一起使用“新”会议)。

至于ob_end_flush(),我相信那是因为你从来没有打过电话ob_start()。您可以使用ob_get_level()检查ob *级别并在循环之前使用ob_end_clean(),然后 instate a ob_start()/ob_end_flush()对在循环内安全地刷新。

+0

谢谢你的回答。我喜欢创建我自己的数据保存机制的想法。我想到的唯一问题是,文件名是什么?我会在哪里存储它?如何删除文件后不再使用?我的意思是,如果一个用户只是关闭他们的浏览器,服务器不知何故将需要删除该文件作为垃圾。 – Jaylen

+0

您将需要垃圾回收(就像PHP本身一样)。或者一个守护进程;正如我所说,您可以使用Redis存储会话信息,并让它执行任何需要完成的任务。如果使用session_save_handler,垃圾回收将由PHP自动完成。 – LSerni

+0

谢谢。我写了一个类来处理会话之外的缓存。感谢您的建议 – Jaylen

0

而不是为每个循环启动会话,只有在它尚未启动时才启动它。

对于PHP 5.4及更高版本:

if (session_status() == PHP_SESSION_NONE) { 
    session_start(); 
} 

对于PHP 5.3以下版本:

if(session_id() == '') { 
    session_start(); 
} 

不能调用ob_end_flush(),而不调用ob_start()第一,但你可以只使用ob_flush()什么你正在努力去做。

最后,你在浏览器中做这个吗?如果浏览器需要太长的响应时间,则浏览器将放弃页面,并且无限循环最终会导致超时。你最好使用ajax/javascript或者元刷新标签,而不是在PHP侧循环。

相关问题