从服务器发送数据到客户端? [英] Sending data from server to client?

查看:80
本文介绍了从服务器发送数据到客户端?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个php服务器文件和一个HTML客户端文件,HTML文件每隔 500毫秒向服务器发送ajax请求以检索数据,尽管这可以按预期工作,但会导致内存使用率过高,并且客户端设备上的CPU.

I have a php server file and an HTML client file, the HTML file send ajax requests to the server to retrieve data every 500 ms, this although works as expected it's causing high usage of memory and CPU on the client's device.

PHP

if(isset($_POST['id']) && $_POST['id'] != '' )
{
    $id     = $_POST['id'];
    $select = $con->prepare("SELECT * FROM data WHERE id=?");
    $select->bind_param('s', $id);
    $select->execute();
    $result = $select->get_result();
    while($row = $result->fetch_assoc())
    {
        echo $row['column 1'] . "\t" . $row['column 2'] . "\n";
    }
}

AJAX

function send(){
    var formdata = new FormData(),
        id       = document.getElementById('id').value;
    formdata.append('id', id);
    var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    xhr.open('post', 'server.php', true);
    xhr.send(formdata);
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            console.log(xhr.responseText);
        }
    }
}
setInterval(function(){send()}, 500); 

我想找到一种替代ajax的解决方案,而不是大多数时候向服务器发送大量请求并检索相同的数据,如果服务器可以在数据更改或更新时与客户端进行交互,则效率将大大提高.

I would like to find an alternative solution to ajax, instead of sending numerous requests to the server and retrieving same data most of the time, it would be much more efficient if the server can interact with the client on data change or update.

我无法使用PHP Socket HttpRequest 方法,因为它们未安装在托管服务器上,并且不确定以后是否可以使用.我能想到的唯一方法是使用 SESSIONS .

I can't use PHP Socket or HttpRequest methods as they are not installed on my hosting server and I'm not sure if the later works. The only way I can think of is using SESSIONS.

根据 PHP服务器存储所有用户会话在服务器上同一目录上,因此可以直接在文件上更改特定用户的会话变量.但是问题是这些文件中的数据已序列化,我不确定如何对数据进行反序列化并重新序列化然后保存新数据!

According to this PHP server store all users sessions on the same directory on the server, therefore it may be possible to change sessions variables for a particular user directly on the file. The problem however is the data in those files are serialized and I'm not sure how to de-serialize the data and re-serialize them and then save the new data!

即使我能够找到一种在会话文件上存储更新的方法,我仍然需要使用setInterval来每隔 500ms 监听会话的变量更改,尽管这并不理想,但是就内存和CPU使用率而言,比使用 XMLHttpRequest 更好.

Even if I was able to find a way to store updates on the session file, I still need to use setInterval to listen to the session's variable change every 500ms although it's not ideal but it would be much better than using XMLHttpRequest in terms of memory and CPU usage.

那么最好的方法是什么?任何帮助将不胜感激.

So what's the best way to do this? any help would be much appreciated.

更新:

我意识到 SESSION 将无法正常工作,因为它只能由服务器而非客户端读取,因此我必须向服务器发送ajax请求以获取我试图避免的变量.

I realized that SESSION wont work because it can be read only by the server not the client, therefore i have to send ajax request to the server to get the variables which i was trying to avoid.

我尝试了长时间轮询,但是我遇到了很多问题, flush ob_flush()在我的服务器上不起作用,并且我无法更改 ini 设置.尝试无限循环时,我无法让它在数据更改时中断:

I tried long polling but i had many problems with it, flush and ob_flush() doesn't work on my server and i can't change the ini settings. When trying the infinite loop i can't get it to break on data change:

if(isset($_GET['size']) && $_GET['size'] != '')
{
    $size = (int)$_GET['size'];
    $txt = "logs/logs.txt";
    $newsize = (int)filesize($txt);    
    while(true) {
        if($newsize !== $size) {
            $data = array( "size" => filesize($txt), "content" => file_get_contents($txt));
            echo json_encode($data);
            break;
        }
        else{
            $newsize = (int)filesize($txt);
            usleep(400000);
        }
    }
    
}

它不断地工作,即使 logs.txt 的大小增加也不会中断!如何使它断开并在大小增加时回显数据?

it keeps going on and on, even if the logs.txt size increase it won't break! how can I make it break and echo data on size increase?

更新2:

事实证明,调用 filesize()方法时php缓存文件大小,因此上述循环将无限期运行,解决方案是使用 clearstatcache()方法这将清除存储的文件大小的缓存,从而使循环在文件大小更改时中断.

It turned out the php cache the filesize when calling filesize() method therefore the above loop will run indefinitely, the solution for that is to use clearstatcache() method which will clear the stored cache of the file size allowing the loop to break on filesize changes.

推荐答案

好吧,经过许多测试和长期研究,我得出的结论是,除非客户端向服务器发送请求,否则PHP服务器永远无法直接与指定的客户端进行交互.首先.

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.

我发现的唯一可靠的解决方案是使用无限循环,该循环只会在数据更改时中断,这将大大减少对服务器的Ajax请求的频率,从而提高性能并减少内存和CPU的使用.客户的设备,方法如下:

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(处理数据更新或向数据库中插入新数据):

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

以上代码将插入/更新数据,创建文件 log.txt (如果不存在),并在每次请求时向其添加其他文本. log.txt 稍后将在下面的无限循环中使用,并且在更改大小时会中断循环.

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(处理读取数据请求):

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

这不是理想的解决方案,但是它将我的xmlhttp请求从2/sec降低到1/25 sec,希望有人能够提出更好的解决方案.

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.

这篇关于从服务器发送数据到客户端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆