2

I am currently implementing a long polling function in Codeigniter and have come up a problem.

Lets say I have a normal PHP Controller:

function longpolling()
{
    //PHP Timelimit infinite
    set_time_limit(0);

       while(true){  
                    echo "test";

                   //Sleep 3 Seconds
                     sleep(3);
             }
}

The page is just saying loading when called and does not return "test" instead you get 404 Error after a while.

What am I doing wrong?

Thank you!

zer02
  • 3,963
  • 4
  • 31
  • 66
  • I just checked the error.log `2012/11/21 17:52:04 [error] 28833#0: *45 upstream timed out (110: Connection timed out) while reading response header from upstream, client: XXX, server: _, request: "GET /index.php/notification/longpolling HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "XXX" 2012/11/21 17:52:04 [error] 28833#0: *45 open() "/usr/share/nginx/html/50x.html" failed (2: No such file or directory), client: XXX, server: _, request: "GET /index.php/notification/longpolling HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "XXX"` – zer02 Nov 21 '12 at 14:52
  • You have to eventually end the response. Check out the following post: [Simple “Long Polling” example code?](http://stackoverflow.com/questions/333664/simple-long-polling-example-code). – juan.facorro Nov 21 '12 at 14:55
  • using die() prevents any further echo outputs it seems – zer02 Nov 21 '12 at 15:11

3 Answers3

0

You aren't doing anything 'wrong' it's just that php doesn't work the way you're expecting it to.

If you did it like this:

$i = 0;
while ($i < 10)
{
    echo "Hi There!";
    sleep(2);
    $i++;
}

It will eventually output lots of Hi There, but not one at a time, rather it will all display at the end of the while loop.

You could even throw a flush() in there

$i = 0;
while ($i < 10)
{
    echo "Hi There!";
    flush();
    sleep(2);
    $i++;
}

And you still wont get anything until the very end.

Because your while(true) never ends you will never see any output, and I assume the browser timeout kicks in? Or the max_execution_time setting is reached?

Just popped into my head now: It might work if you wrote some data to a file in an infinite loop I have never tried it myself.

Dale
  • 10,384
  • 21
  • 34
  • Hi, there is a example file which uses while(true) which is actually the essence of longpolling?! http://code.google.com/p/jquery-longpolling/. It works there.. – zer02 Nov 21 '12 at 14:57
  • As I understand (possibly wrongly so) if the request is never closed, which happens under a while(true) loop with no break, then jquery will not fire the success event of an ajax call? I could be wrong on that though. – Dale Nov 21 '12 at 15:01
  • It will fire ;) You check the example file inside jquery longpolling. I tried it on my local XAMPP Server. Thats why I am confused why it doesnt work inside codeigniter. :) – zer02 Nov 21 '12 at 15:05
  • Right I tried the demo and I'm not sure what was supposed to happen but I waited for ages and then all the results showed up at once and it only happened once? – Dale Nov 21 '12 at 15:12
  • I've just seen that there is an exit() thrown in there when it has looped 20 times so I don't see anything different to what I said in my answer. – Dale Nov 21 '12 at 15:14
  • you have to open the html file. then when you change the values inside the txt file it will refresh inside your browser. I need test once at a time ;) not 20 at once. – zer02 Nov 21 '12 at 15:15
  • 1
    I see, still though when the file changes it still exit()'s the script which forces the content out, yours will hang forever because it never exits! – Dale Nov 21 '12 at 15:23
  • Ah yes i didnt see the exit ;) Thank you – zer02 Nov 21 '12 at 15:30
0

I've ran into issues like this myself. You'll have to look into flushing the output out as php and/or the webserver might be buffering the data until a certain threshold is met. I had a horrible time struggling with IIS over this, I think Apache is a lot easier to manage. Plus there's telling the webserver what to do as well. For apache, here's a snippet found on php.net:

I just had some problems with flush() and ob_flush(). What I did to resolve this problem took me some time to figure out so I'd like to share what I came up with.

The main problem is the php setting "output_buffering" which can be set too large and will prevent your text from outputting. To change this value you can either set it in php.ini or you can add the line

php_value output_buffering "0"

to your .htaccess file. It will not work with ini_set() since it is PHP_INI_PERDIR.

This is combined with the flush() function used before sleep(). I also had to output over a number of characters before it started flushing properly:

    public function longpolling()
    {
        echo str_repeat(" ", 1024); flush();
        for( $i = 0; $i < 10; $i++) {
            echo $i."<br/>";
            flush();
            sleep(1);
        }
    }

Also. I just tried this on my server and it wouldn't work until I added the php_value line to my htaccess file. Once I did, it worked as expected.

Recognizer
  • 746
  • 1
  • 7
  • 17
  • This example works on normal php localhost http://code.google.com/p/jquery-longpolling/.Why can´t this work on codeigniter? – zer02 Nov 21 '12 at 15:12
  • I've updated my answer. The extra part that worked with my pyrocms (based on codeigniter so it should work) was to put the `echo str_repeat(" ",1024); flush();` line in. That was within a controller and that line was necessary. You may or may not need to adjust the number of characters to output first. 1024 worked for me, but 700 did not. – Recognizer Nov 21 '12 at 16:21
0

The page will keep loading until the PHP file execution has reached the end of the file. PHP doesn't work like C or C++. You make a request and when everything is done you get the output. Once the page is loaded no PHP is executing anymore.

And sleep() is just used to slow PHP down in some cases. In this case:

echo "Something";
sleep(30);
echo " else";

"Something" and " else" will be printed at the same moment while the total execution will take 30 seconds more.

Shoe
  • 74,840
  • 36
  • 166
  • 272