How to determine socket resource has completed buffering? - php

Firing a command to socket resource and getting the output takes some decent amount of time in PHP.
I have written code to read the buffered output string after sleep duration of 1 second and it works fine.
If i don't provide any delay after fputs, i don't get any string.
How to determine this time? putting time duration by hit and trial can cause trouble.
For safe side i always put time in seconds.
What parameters affect this time, does anyone has statistical data?
$socket = fsockopen($ip,3083);
$command = 'RTRV-NE-GEN:::123;';
fputs($socket,$command);
sleep(1);
$string = fread( $socket, 3000 );

You probably just need to do fflush($socket); there after you do fputs(...).

Related

How to show all output from fread socket unix in PHP?

I try show output from socket but the return is showed cut.
<?php
$socket = '/var/run/qemu-server/121.serial1';
$sock = stream_socket_client('unix://'.$socket, $errno, $errstr);
fwrite($sock, $argv[1] . "\r\n");
$data = '';
while ($buffer = fread($sock, 8128)) $data .= $buffer;
echo $data;
fclose($sock);
?>
I need this output:
{"VMid":"121","Command":"ls /","Output":"bin\nboot\ndev\netc\nhome\nlib\nlib32\nlib64\nlibx32\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsnap\nsrv\nswap.img\nsys\ntmp\nusr\nvar\n"}
But it only returns:
{"VMid":"121","Command":"ls /","Output"
I tried "stream_set_read_buffer", "file_get_contents" and no success.
I presume here that the server has not had time to fully respond by the time you are polling. You can quickly test this theory by putting a sleep() after you send the instruction (fwrite) before you poll (fread). That's a test solution, not final (as you never know how long to "sleep" for).
What you need for sockets generally are a continuous poll (while loop that basically never ends, but under control so you can pause / exit etc), and continuous buffer read/write (append new content to a buffer; when you either reach the end of expected message OR you read the number of bytes you expect* remove that content from the front of the buffer and leave the remainder for next loop. You can, of course, bomb out at this point if you have everything you need and close the socket or return to polling later.
A common trick is to set the first two/four bytes of the message to the length of the payload, then the payload. So you constantly would poll for those two/four bytes and then read the content based of that. Probably not possible with another system like QEMU, so you'll need to look instead for...? EOL/NL etc?

Excel Data Too large to parse. Execution Time Out

I am using laravel and using https://csv.thephpleague.com/ to parse csv.
My function is something like
$path = $request->file('import_file')->getRealPath();
$csv = Reader::createFromPath($path, 'r');
$csv->setHeaderOffset(0);
$csv_header = $csv->getHeader();
$sample_data = $csv->fetchOne();
$sample_data = array_values($sample_data);
$records = $reader->getRecords();
$csv_file_id = Csv_data::create([
'csv_filename' => $request->file('import_file')->getClientOriginalName(),
'csv_header' => json_encode($csv_header),
'csv_data' => json_encode($records)
]);
How can i parse large data sets, by dealing against execution time limit.
Well, am pretty new to these things, so I request just not commenting like use this and that. Up to now time is just passing by trying this and that package. So, solution with code snippets could be better.
Also I tried with,
$stmt = (new Statement())
->offset($offset)
->limit($limit)
;
But with no success. !st reason even limiting offset and running in loop by increasing offset, it shows same error of execution time. 2nd reason, its little difficult for me to end the loop with good logic.
Looking for some help. I will be available for instant reply.
Are you using a console command for this?
https://laravel.com/docs/5.6/artisan
If you run into memory limits when doing through console, you can first try to increase php memory limit.
If that is still not enough, last option is to cut up .csv into parts.
But this should not be necessary unless you are dealing with a very vert large .csv (unlikely).
By default, PHP is usually set to execute a HTTP request for 30 seconds before timing out -- to prevent a runaway script or infinite loop from processing forever. It sounds like this is what you're running into.
The quick and dirty method is to add ini_set('max_execution_time', 300); at the top of your script. This will tell php to run for 300 seconds (5 minutes) before timing out.
You can adjust that time as needed, but if it regularly takes longer than that, you may want to look at other options -- such as creating a console command (https://laravel.com/docs/5.6/artisan) or running it on a schedule.

Pause-Continue reading large text file with php

I have the below PHP code. I want to be able to continue reading the text file from the point it stopped, and the text file is over 90mb.
Is it possible to continue reading from the point the script stopped running?
$in = fopen('email.txt','r');
while($kw = trim(fgets($in))) {
//my code
}
No, that's not easily possible without saving the current state from time to time.
However, instead of doing that you should better try to fix whatever causes your script to stop. set_time_limit(0); and ignore_user_abort(true); will most likely prevent your script from being stopped while it's running.
If you do want to be able to continue from some position, use ftell($in) to get the position and store it in a file/database from time to time. When starting the script you check if you have a stored position and then simply fseek($in, $offset); after opening the file.
If the script is executed from a browser and it takes enough time to make aborts likely, you could also consider splitting it in chunks and cleanly terminating the script with a redirect containing an argument where to continue. So your script would process e.g. 1000 lines and then be restarted with an offset of 1000 to process the next 1000 lines and so on.

Timed loop in php

I just want to print a counting from 1 to 10 at an interval of 10 sec between each integer.
eg.
$i=10; //Time delay
for($j=1;$j<11;$j++)
{
echo $j;
//do something to delay the execution by $i seconds
}
I have tried everything including flush(), ob_flush(), ob_implicit_flush() but all i get is a frozen screen untill the whole time is executed.
http://php.net/manual/en/function.sleep.php
The sleep function will interrupt execution of your script.
But have you considered using Javascript for something like this? Your script may reach maximum execution time, and will be hogging resources on the server. Use the client's resources instead!
What you want is much more javascript-related than PHP. Because PHP is serverside it is not designed to do these kind of operations. You COULD get it to work, but it would not be very pretty.
In my logic; counting from 1 to 10 should not involve the server at all. You can do this directly in the browser, hence use javascript.
you want to print the countdown while your php script is running?
if yes, then try that non-recommended fragment:
ob_start();
for($i=0;$i<10;$i++) {
echo str_repeat(" ",10000);
echo 'printing...<br />';
ob_flush();
flush();
sleep(1);
}
you see, the strange line:
echo str_repeat(" ",10000);
it seems that browsers needs some "data" before deciding to really flush your data.
Use javascript for real time counters.
Use jQuery. On $(document).ready add a delay of 10 seconds to show a specific div which would contain the info to appear after 10 seconds.
For ready - http://api.jquery.com/ready/
For delay - http://api.jquery.com/delay/
Yes, use Javascript as it's not possible to accomplish this task with PHP using HTTP because of output buffering.

Read constant UDP stream in php

how do i go about reading data being sent almost constantly to my server.
the protocol is udp. if i try to read in a while(1) loop, i dont get anything. it seems like the read will only echo once all the reading is done. so it waits till the loop is done reading which it will never be. i want the socket_read to echo immediately when it gets the data. here is the code that doesnt work. thanks in advance.
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, $local, $port) or die('Could not bind to address');
//this is where the reading loop should go.
while(1)
{
echo socket_read($sock,1024);
}
socket_close($sock);
?>
Try calling flush() immediately after that echo statement.
Something like this might help:
do {
echo socket_read($handle,1024);
$status = socket_get_status($handle);
} while($status['unread_bytes']);
OR
while ( $buffer = #socket_read($sock,512,PHP_NORMAL_READ) )
echo $buffer;
The PHP manual entry on socket_read() is a little vague when it comes to how much (if any) internal buffering it's doing. Given that you are passing 1024 in for the length, that specifies that it should return after receiving no more than 1024 bytes of data.
Disclaimer: the following is just speculation, as I have no knowledge of the internal implementation of socket_read().
If the socket_read() function is using its length parameter as a hint for an internal buffer size, you might see bad performance with small UDP packets. For example, if socket_read() waits for 1024 bytes of data regardless of the size of the packets, if you are constantly receiving 60 byte UDP packets it'll take a while for the buffer to fill and the function to return.
(Note: after looking up the "unread_bytes" field mentioned by Tim, it looks like PHP does keep internal buffers, but it makes no mention of how large or small those might be.)
In this case, socket_read() will return larger chunks of data once its buffers fill to reduce processing resource consumption, but at the expense of higher latency. If you need the packets as past as possible, perhaps setting a lower length field would work. That would force socket_read() to return sooner, albeit at the expense of executing your loop more often. Also if you set the length too low, your socket_read()'s might start returning incomplete packets, so you'll have to account for that in your code. (If that matters for your application, of course.)
I needed to call ob_flush();. Never even heard of it before. turns out my problem wasn't the loop, but the fact that php naturally waits till script is done before actually sending the internal buffer to the web browser. calling flush(); followed by ob_flush(); will force php to send whatever buffer it has stored to the browser immediately. This is needed for scripts that will not stop (infinite loops) and want to echo data to the browser. Sometimes flush() doesn't work as it didn't in this case. Hope that helps.

Categories