0

I've been working on a web interface for iPerf and it's going pretty well. My goal is to have the output of the commands be streamed live on the page. It works for iPerf2 commands but when I run iPerf3, it only shows the output once the entire test is complete.

Based on my research I've done on this site and others, I'm thinking it might have something to do with the buffer. I've been messing around with flushing the buffer at different times or setting the 'fread' length to different values but I can't get it to act the same as regular iperf commands. I think this because instead of running the 'popen' on the iperf command itself, I used popen on a python script that would run the iperf command. This still returned the same issue. It only shows the output on the web page once the entire test is complete.

Here is my code:

phpQ.php

<!DOCTYPE html>
<html>
<body>

    <div>
        Server Domain/IP Address: <input id="address" type="text"><br>
        <input id="run" type="button" value="iPerf"><br><br>
    </div>
    <div id="result"></div>
    <script>
        function updateText(address) {
            var ajax = new XMLHttpRequest();

              ajax.onreadystatechange = function() {
                if (this.readyState == 3) {
                  var old_value = document.getElementById("result").innerHTML; 
                  document.getElementById("result").innerHTML = this.responseText;
                }               
            };

            if (purpose == 1) {
                var url = 'ajaxQ.php?address='+address;
                ajax.open('GET', url,true);
                ajax.send();
            }    
        }

        document.getElementById("run").onclick = function(){
            address = document.getElementById("address").value;
            purpose = 1;
            updateText(address);
        }

    </script>
</body>
</html>

ajaxQ.php - to see the difference, change "iperf -c" to "iperf3 -c" in the $iperfCmd variable.

<?php

function liveExecuteCommand($cmd,$address)
{
    while (@ ob_end_flush()); // end all output buffers if any

         // tells the user what command is going to run
    echo "<pre>Running Command: '".$cmd."'</pre>";
   
        // open the command to run and read output 
    $proc = popen("$cmd", 'r');
    $live_output     = "";
    $complete_output = "";

    while (!feof($proc))
    {
        @ flush();
        $live_output     = fread($proc,4096);
            // adds the live output to the complete output 
        $complete_output = $complete_output . $live_output;
            // prints the live output 
        echo "<pre>$live_output</pre>";

    }
    sleep(1);
        // close the process 
    pclose($proc);
    echo "<pre>------------------------------------------------------------\nAll Done!</pre>";
}
    // this happens if the iPerf button is pressed
if (isset($_GET['address'])) {
    $address =  $_GET['address'];
    $iperfCmd = "iperf -c ".$address." -i 1 -t 5";
    liveExecuteCommand($iperfCmd,$address);
} 

else{
    echo "No post request";
}

?>

FYI, I am running the iperf client on an 'Ubuntu 16.04.2 LTS' CLI server and the iperf server on an 'Ubuntu 16.04 LTS' desktop server.

Thanks for any help!

SterlingB
  • 69
  • 8
  • flushing buffers just doesn't work with ajax. It only returns data once the whole call is complete. It's not really anything you've done wrong, it's just not something that's supported via ajax. So you either have to repeat the ajax call at a set interval, to keep polling the server for the latest results, or use some other architecture such as server-sent events or websockets which is more suited to this kind of "streaming" type use case. – ADyson Oct 04 '17 at 15:13
  • Actually an edit to the above. It some cases it _may_ be possible for this to work, but it will depend on other things on the server config, and also may not be totally reliable. Reading https://stackoverflow.com/questions/19750274/how-dos-xhrs-readystate-3-work, https://stackoverflow.com/questions/42480685/php-flush-loop-with-ajax, https://stackoverflow.com/questions/35697301/php-flush-information-in-controller and http://php.net/manual/en/function.flush.php was instructive – ADyson Oct 04 '17 at 16:09
  • @ADyson Thanks for your response! I'll look into that and post back with results. – SterlingB Oct 04 '17 at 16:11
  • @ADyson Well I have tried all the different flush types and no luck. The frustrating thing is that I can get live streaming to work with ping commands and iperf2 but just not iperf3. If you could, can you please give me an example of how to poll the ajax? I'm looking into it and it seems that it can be as easy at "setInterval()" but with my current function setup, I'm not sure how to deploy it. Would it be: "setInterval(updateText,1000);" or "setInterval(ajax,1000);" or "setInterval(ajax.onreadystatechange,1000);" or what? Thanks again for the help! – SterlingB Oct 04 '17 at 18:10
  • it would be the "updateText" call. But I'd do it less often than every second, unless your call completes extremely quickly, or you might get concurrency situations where you start the next request before the previous one finishes (ajax runs async). You'd also need to change the server-side so it just reads the data once each time it runs, and doesn't sleep, and maintains the state between calls (e.g. using sessions or a database) so it knows what it sent to the client last time, to avoid duplicate output. – ADyson Oct 04 '17 at 18:54
  • Another thought - how does iperf3 work? I don't know anything about it. Does _it_ definitely stream its output? – ADyson Oct 04 '17 at 18:56

0 Answers0