1

Im trying to use SSE in PHP backend to send messages to a user.

the functional part of the backend code looks like-

<?php
set_time_limit(0);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(0);
@session_start();
    ob_start();
    echo "retry: 1000\n";

    ob_flush();
    flush();

    require_once 'sql_connection_class.php';
    require 'chatbox_class.php';

    $chatbox=new chatboxclass($_GET['friendid']);

    function recursivesenddata(){
    global $chatbox;
    $jsonobj=$chatbox->jsonloadunreadmessages();

    //append json object


if($jsonobj!=-1){

>           echo "data:{$jsonobj}\n\n";
>           ob_flush();
>           flush();
>         }else{
>           //don't send anything   
>         }
    }



while(true){
      recursivesenddata();
      session_write_close();
      sleep(1);

    }
?>

it appears that ignore_user_abort(0) doesn't do anything when the user closes the page.

in $chatbox->jsonloadunreadmessages() there is a function that should only be executed when the page is open, it updates things in mySQL database. but this script keeps on running on the server even when the page is closed!

is there anyway to check on the server side when the user has closed the page to exit the infinite while loop?

JasonY
  • 752
  • 10
  • 24
  • Why do you do an infinite loop? As I understand it thet the code should only be called when there are updates. How do you initiate the server calls? – bestprogrammerintheworld Mar 04 '15 at 09:56
  • i need it to keep running as long as the user is on the page, i can exit the loop after x number of sleeps and just send a retry if there isn't a more elegant solution – JasonY Mar 04 '15 at 10:01
  • I maybe be incorrect here, but couldn't you just do an ? – bestprogrammerintheworld Mar 04 '15 at 11:26
  • oh sorry, i didn't specify that this php file is called using javascript by for example =>var source = new EventSource("demo_sse.php"); the script is left hanging on the server to only send messages when there is one, hence the infinite loop. but there is no way to stop it from the client side once initiated :( – JasonY Mar 04 '15 at 14:09

2 Answers2

1

The PHP script should be killed as soon as the connection socket closes. If the script keeps on running when the user closes the page, there is something very wrong with your Apache/PHP configuration.

Socket closing can happen when the client calls EventSource.close() explicitely, the connection is lost due to network problems, the client closes the page or your PHP script terminates.

ignore_user_abort(false) does nothing; that's the default behaviour (the script terminates when the connection is closed). Passing true as a parameter would have your script survive the connection, but that would not solve your problem.

Your retry: 1000 serves no purpose since you're never closing the socket server-side. Your PHP script should be called when the client activates an EventSource object and terminate only at the client's request (or if the network fails), so whatever initial DB tweaking should occur only once per chat connection. That's assuming the client does not do anything that would close the connection.

Btw this will put a lot of strain to the server: you will have one PHP process per chatting client running for the whole chat duration, and the polling period is about 10 times too small (10 seconds is more than enough). Having the clients poll for new messages every 30 seconds or so would be less wasteful.

kuroi neko
  • 8,479
  • 1
  • 19
  • 43
  • Hi, thanks for the response. there is definately something wrong with my Apache/PHP config, im testing the code on xampp btw. its to the point where when i close the sse script and manually insert a row into sql in phpmyadmin, that row gets automatically updated as if the sse is still running, and when its only when i disconnect and reconnect xampp's Apache and MySQL, that row stops updating. The retry 1000 was just put there so retry would be 1 second instead of the default 3 when an unexpected error occurs during transmittion. – JasonY Mar 04 '15 at 16:18
  • Also, 30 seconds is not very real time for a chat application. if you need to call retry everytime a db tweaking occurs, how is this different from ajax long polling? I just added a condition on my while loop to make it time out after 30 seconds if nothing is being sent and calls retry, although i had to rewrite a lot of code in the chat class for this to be a solution. sorry to sound so amateur, im quite new to php and server side stuff – JasonY Mar 04 '15 at 16:18
  • Well in your case long polling seems the best solution to me. As for the 30 seconds delay, you could put 10s if your customers are little kids with no tolerance to frustration, but it certainly would be a mighty waste of bandwidth, computing power and electricity IMHO. – kuroi neko Mar 04 '15 at 17:05
0

ignore_user_abort() is ignored on IIS Systems and may be prevented by your configuration.

Try to use connection_aborted() in your while loop:

while ( connection_aborted() == 0 ) {
    recursivesenddata();
    session_write_close();
    sleep(1);
}
Daniel
  • 795
  • 1
  • 10
  • 25
  • thanks for the response, it seems that connection_aborted() keeps on returning 0 even when the tab is closed, i have changed ignore_user_abort= Off on php.ini file with no luck. – JasonY Mar 04 '15 at 10:09