views:

60

answers:

3
+1  Q: 

PHP fread problem

hi guys,

ive ran into an issue while creating a PHP telnet script at work to gather network data.

as the amount of data returned from the 'Action: Status' command could be of any size... im concerned about using a static number with fread() on line 13. I have also tried using fgets() instead but it only grabs the first line of data (the META HTTP line... without the table). how can I grab an arbitrary amount of data from the socket using PHP? please help

<?php
$ami = fsockopen("192.100.100.180", 5038, $errno, $errstr);

if (!$ami) {
echo "ERROR: $errno - $errstr<br />\n";
} else {

    fwrite($ami, "Action: Login\r\nUsername: 1005\r\nSecret: password\r\nEvents: off\r\n\r\n");

    fwrite($ami, "Action: Status\r\n\r\n");
    sleep(1);

    $record = fread($ami,9999);#this line could over run!!!
    $record = explode("\r\n", $record);
    echo "<META HTTP-EQUIV=Refresh CONTENT=\"9\">"; #refresh page every 9 seconds
    echo "<table  border=\"1\">";


    foreach($record as $value){
        if(!strlen(stristr($value,'Asterisk'))>0
        && !strlen(stristr($value,'Response'))>0
        && !strlen(stristr($value,'Message'))>0
        && !strlen(stristr($value,'Event'))>0
        && strlen(strpos($value,' '))>0) #remove blank lines
        php_table($value);;
    }

    echo "</table>";

    fclose($ami);
    }


function php_table($value){
        $row1 = true;
        $value = explode(" ", $value);
        foreach($value as $field){
            if($row1){
                echo "<tr><td>".$field."</td>";
                $row1 = false;
            }
            else{
                echo "<td>".$field."</td></tr>";
                $row1 = true;
            }
        }
}

?>
+1  A: 
while (strlen($c = fread($fp, 1024)) > 0) {
    $record .= $c;
}

Edit: Your application hangs because it's not closing the connection to signify the end of a HTTP request. Try

fwrite($ami, "Action: Status\r\n\r\n"); 
fwrite($ami, "Connection: Close\r\n\r\n");
Saul
Much better to check for the end of the file with feof()
Cfreak
unfortunately this code example also hangs
JB87
thanks saul, although you are correct that it no longer hangs.. it seems to take about 85secs to load which is too long for the spec requirements.. in fact, the table never loads in before the page refreshes (10secs)
JB87
@JB87: Does it load for 85 secs even after adding the "Connection: Close"?
Saul
thanks saul, was just testing your edit now. the correct syntax for the Asterisk AMI is fwrite($ami, "Action: Logoff\r\n\r\n"); which is now working perfectly! hopefully logging in and out of the system to sample data wont cause problems in the future but thanks for spotting this critical error on my part
JB87
A: 
$data = '';
while (!feof($ami)) {
  $data .= fread($ami, 1024);
}

or in php5

$data = stream_get_contents($ami);
Raoul Duke
i have tried both methods, and both just hang reading 'waiting for localhost'..... I have increased my chunk size on the first example but it has had no effect
JB87
probably because the remote end doesn't close the connection. in that case you will have to use the fread variant and determine yourself when to stop.
Raoul Duke
I see... but how can I make it stop when it is in the middle of processing the loop connection?
JB87
There has to be something in the response from the remote end which indicates that it's finished and you just look for that and break the loop if it occurrs, for example if the response terminates with "\r\n": while(substr($data, -2) != "\r\n") { $data .= fread($ami, 1024); }
Raoul Duke
A: 

Just use a loop and look for the "end of the file"

$record = '';
while( !feof( $ami ) ) {
    $record .= fread($ami,9999);
}

You should probably consider using smaller chunks.

Cfreak
even with these large chunks, the application is now hanging indefinitely
JB87
Ok. Since it hangs then the remote is not closing the connection. What you could do is check $record each time through your loop to see if you have what you're looking for and then break out once you do.
Cfreak