3

I'm using in my project server-sent events where the JS is calling a PHP page, say eventserver.php which consists basically of an infinite loop which checks the existence of an event in a $_SESSION variable. On my first implementation this lead my website to hung up because the eventserver took the lock on the session and did not release it until the timeout expired; however, I managed to resolve this issue by locking/unlocking the session by using session_write_lock() and session_start() continuously in the loop.

This is actually causing a lot of PHP warnings (on Apache error.log) saying that "cannot send session cache limiter - headers already sent", "cannot send session cookies" and so on.

Posting some code here

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 );
        }          
    }
}

Why is this happening?

DanMan
  • 11,323
  • 4
  • 40
  • 61
Socket2104
  • 122
  • 2
  • 9
  • And, of course, you've dutifully googled "cannot send session cache limiter - headers already sent" before asking, yes? – Denis de Bernardy Nov 23 '13 at 14:09
  • 3
    wouldnt it be much better if you used system's CRON instead of a looped script ? – Gadoma Nov 23 '13 at 14:09
  • 1
    For constant polling for an event from client side, you may want to look into Ajax. (There's a technique called "long polling" too but it doesn't go well with vanilla PHP AFAIK - [How to implement Comet ?](http://stackoverflow.com/q/8118828) – Pekka Nov 23 '13 at 14:10
  • Ofcourse I searched for an answer but my case is a bit different. FYI I already tried ajax/long-polling but I didn't achieved the result I needed, AFAIK server-sent events (or websockets, but I need only a "one-way" communication) is the best tecnique to implement my needs – Socket2104 Nov 23 '13 at 15:24
  • Possible duplicate of [Pages with session\_start() don't load when server-sent event is running](https://stackoverflow.com/questions/17621175/pages-with-session-start-dont-load-when-server-sent-event-is-running) – Toastrackenigma Sep 05 '19 at 07:30

4 Answers4

1

I am doing the same thing as the OP and ran into the same issue. Some of these answers don't understand how eventSource should work. My code is identical to yours and uses a session variable to know what view the user is on which drives what data to return in the event of a server trigger. It's part of a realtime collaboration app.

I simply prepended an @ to the session_start() to suppress the warnings in the log. Not really a fix, but it keeps the log from filling up.

Alternatively, not sure how well it would work for your application, but you could use ajax to write the session variable you are monitoring to the database, then your eventSource script can monitor for a change in the DB instead of having to start sessions.

Mike
  • 168
  • 11
0

This is not a good idea. HTTP is a request-response protocol so if you want server-client communication to be bi-directional you will need to look into websockets or something similar. There are also things like "long polling" and "heart beating"

If you want an event loop try something like servlets in apache tomcat.

You will grapple for hours with issues because of your design.

Also check out ajax if you just want to shoot messages from javascript to PHP.

Make sure you know an overview of the tech stack you are working with :)

ddoor
  • 5,819
  • 9
  • 34
  • 41
  • I may not have explained my case in the best manner: I don't need a "two-way" communication, but only a server -> client communication. FYI I'm already using ajax to asynchronously communicate with the server-side. – Socket2104 Nov 23 '13 at 15:26
  • Why the infinite loop then? – ddoor Nov 23 '13 at 15:28
  • Whenever a server notification event occurs, the code inside the loop reads it and notificates to the listening client-side JS. AFAIK there's no other way to do that with SSE – Socket2104 Nov 23 '13 at 15:36
  • Like I said, HTTP is a request-repsonse protocol. Client makes request, server sends response. If you want the server to push async data to client you need bi-directional. Otherwise you have to wait for the client to make a request to serve the "notification" data. You could try setting your client up to poll the sever, that would make more sense. – ddoor Nov 23 '13 at 15:41
  • 2
    I'm setting up a JS with an onload event containing "var source = new EventSource( 'eventserver.php' );" and then attaching some listeners like "source.addEventListener( 'event', callback())". This is not an HTTP request :) EventSource uses stream – Socket2104 Nov 23 '13 at 15:51
  • 1
    @Socket2104 This person obviously has never heard of SSE's – Shawn31313 Apr 11 '16 at 00:19
0

You don't need an infinite loop with SSE. The EventSource keeps an open connection to the server and any update on the server side data will be read by the client.

Check out basic usage of SSE here

0

It's probably because you start the session twice in your code. Don't restart the session at the beginning of the loop, but after the sleep().

DanMan
  • 11,323
  • 4
  • 40
  • 61