I have a problem with ajax comet - after the page is loaded everything works greate but when I try to open other page on the same host (some menu or link) this page is loaded after long time (very slow).
Server is Slackware 13.37 Apache/2.2.20 PHP 5.3.8 and script is backend.php:
<?php
function my_abort_handler( ) {
write2file(connection_status() . ' SD Aborted!!!');
}
register_shutdown_function('my_abort_handler');
try {
error_reporting(0);
session_start();
if (!isUserLogedIn()) {
$return['message'] = "Login required";
$return['error'] = true;
echo json_encode($return);
exit();
}
if (empty($_SESSION['return'])) {
$_SESSION['return'] = false;
}
connectToDB();
while (!connection_aborted()) {
write2file(connection_status() . ' SD Aborted!!!');
$return = collectDataFromDB();
$d1 = array_diff_assoc($return, $_SESSION['return']);
$d2 = array_diff_assoc($return, $_SESSION['return']);
if ((!empty($d1)) || (!empty($d2))) {
$_SESSION['vote_return'] = $return;
echo json_encode($return);
flush();
ob_flush();
exit();
}
sleep(1);
}
} catch (Exception $e) {
$return['message'] = $e->getMessage();
$return['error'] = true;
echo json_encode($return);
}
On the client:
var xhReq = false;
function runComet() {
xhReq = GetXmlHttpObject();
xhReq.open("GET",'backend.php',true);
xhReq.onreadystatechange=consoleinfo;
xhReq.send(null);
}
function consoleinfo() {
if (xhReq.readyState == 4) {
if (xhReq.status == 200) {
console.info(xhReq.responseText);
} else {
console.info("Error Status:" + xhReq.status);
}
runComet();
}
runComet();
Seteps:
I create very simple case - backend return time() on every sec. and on refresh of the page browser: -waits around 30 - 60 sec until I see abort message in the log file or -realod the page but in the log file there is no abort. Every relod add new worker in http://localhost/server-status and rows added in log file are the same as the workers.
I try this on CentOS 5.5 server and the result was the same. I use the defautl apache configuration (only add some virtual hosts and enable server-status).
I think there is a problem with configurion but I can not understand where. Can you help me to solve this problem.
UPDATE: I use netstat to check what's happening. When the request is active netstat output is:
tcp 0 0 127.0.0.1:35518 127.0.0.1:80 ESTABLISHED 2660/firefox off (0.00/0/0)
and after xhReq.abort()
netstat output is:
tcp 1 0 127.0.0.1:80 127.0.0.1:35518 CLOSE_WAIT 3174/httpd keepalive (7167.02/0/0)
so in this case the connection will be keepalive for 7167 secs and background script will work 7167 secs. May be this is something with the OS configuration.
Problems here are two:
First: slow load of the next page - this is because in every page I use session_start()
. If I start session in backend.php the session will be closed and saved after script finish (because I never write and close it). This is the reason next page is opened so slow (next page also use session_start()
). To fix this problem I remove session_start()
from backend.php but if you add 'session_write_close()' it must solve the problem too.
Second: backend.php does not stop execution - this is because I use mod_php and php can not detect browser disconnectct/close. To detect browser disconnect php script must send some output. In backedn.php I add echo '0'; flush(); ob_flush();
to be executed on every while cycle. So backend.php will output '0' on every cycle and it will detect when browser was disconnected (open other page or stop button was pressed) or closed and it's execution will stop. On the client side I replace .replace(/^0*/, '');
so I remove all unnecessary output.
This solve the problem - now backend script stops it's execution when browser try to open other page and next page (on this server) opens on time.
I was having the same problem but I called my comet ajax function after 10 seconds when page loads like
$(function(){
setTimeout('updateFeed()',10000);
});
and it works like a charm