Sending data from server to client?
Before we had capabilities to use sockets in browsers, we used Long polling. The basic idea is that instead of the browser making requests at regular intervals, the browser will make a request to the server, but the server won't respond until there is something worthwhile to share back to the browser. That means the request could be left open for 10ms or for hours.
After the server responds with something, it is then the browser's job to make a new ajax request. This way, there is always a line open to the server.
Refer to this question for more information.
Answering the part of your question about directly editing a session...
To directly manipulate the session of a user, I will assume you know and can track any user's session ID (perhaps in your database on sign in).
When you need to edit a user's session directly on the server:
- Retrieve user's last known session from the database.
- Call
session_close()
to close the current session (if there is one). - Call `session_name($sessionId)' with the session ID.
- Call
session_open()
to open that session.$_SESSION
should be populated with the session data. You will not need to unserialize anything. - Make your edits to the session.
- Call
session_close()
to reserialize the data.
Alternatively, you could directly open the session file, unserialize()
it, edit the data, and re-serialize()
manually.
Okay, after many tests and long research i came to the conclusion that PHP server can never interact with a specified client directly unless the client send a request to the server first.
The only reliable solution i found is to use infinite loop which will only break on data change, this will reduce the frequency of ajax requests to the server considerably, hence increasing the performance and decreasing the usage of the Memory and CPU on the client's device, here how it goes:
PHP 1 (Handles data update or new data insert to database):
$process = $_POST['process'];
$log = "/logs/logs.txt";
if($process == 'update'){
//execute mysqli update command and update table.
$str = "Update on " . date('d/m/Y - H:i:s') . "\n";//add some text to the logs file (can be anything just to increase the logs.text size)
file_put_content($log, $str, FILE_APPEND);//FILE_APPEND add string to the end of the file instead or replacing it's content
}
else if($process == 'insert'){
//execute mysqli insert command and add new data to table.
$str = "Added new data on" . date('d/m/Y - H:i:s') . "\n";
file_put_content($log, $str, FILE_APPEND);
}
The above code will insert/update data, create file log.txt
if not existed and add additional text to it on each request. log.txt
will be used later in the infinite loop "below" and would break the loop when it's size change.
PHP 2 (handles reading data requests):
if(isset($_POST['id']) && $_POST['id'] != '' && isset($_POST['size']) && $_POST['size'] != '')
{
$id = (string)$_POST['id'];
$init_size = (int)$_POST['count'];
$size = file_exists('logs/logs.txt') ? (int)filesize('logs/logs.txt') : 0;//$size is logs.txt size or 0 if logs.txt doesn't exist(not created yet).
$select = $con->prepare("SELECT * FROM data WHERE id=?");
$select->bind_param('s', $id);
while(true){ //while(true) will loop indefinitely because condition true is always met
if($init_size !== $size){
$select->execute();
$result = $select->get_result();
while($row = $result->fetch_assoc())
{
$data['rows'][] = array(
"column 1" => $row['column 1'],
"column 2" => $row['column 2'],
);
}
$data['size'] = $size;
echo json_encode($data);
break; //break the loop when condition ($init_size != $size) is met which indicates that database has been updated or new data has been added to it.
}
else{
clearstatcache(); //clears the chached filesize of log.txt
$size = file_exists('logs/logs.txt') ? (int)filesize('logs/logs.txt') : 0;
usleep(100000) //sleep for 100 ms
}
}
}
AJAX:
var size = 0; //declares global variable size and set it's initial value to 0
function send(s){
var formdata = new FormData(),
id = document.getElementById('id').value;
formdata.append('id', id);
formdata.append('size', s);
var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('post', 'server.php', true);
xhr.timeout = 25000; //set timeout on xmlhttprequest to 25 sec, some servers has short execution tiemout, in my case it's 27 sec so i set the value to 25 sec.
xhr.send(formdata);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var data = JSON.parse(xhr.responseText);
size = data.size;
console.log(data.rows);
setTimeout(function(){send(size)}, 100); //re-initiate the request after receiving data
}
}
xhr.ontimeout = function(){
xhr.abort(); //abort the timed out xmlhttp request
setTimeout(function(){send(size)}, 100);
}
send(size);
This is not the ideal solution but it reduced my xmlhttp requests from 2/sec to as low as 1/25 sec, hope that someone will be able to come up with a better solution.