timeout for reading a file without EOF (/dev/random)


#1

hi

Is there a posibility in PHP

  • to read a file as stream
  • or to specefy a timeout for reading files as it is with streams
  • or a way to find out wether a file has data in it without EOF

i try to read from /dev/random wich is no problem as long as it is not empty.

But if it is empty it does not return a EOF but hangs the script till there is more data.
filesize() always returns 0.

here is a little funktion showing what i try to do (off cause it doesn’t work as there is no timeout for files):

[php]
function getrand($length=1)
{
$rand=array();
if($devrandom=fopen(’/dev/random’,‘rb’))
{
stream_set_timeout($devrandom,1);
do
{
$rand[]=ord(fgetc($devrandom));
$info = stream_get_meta_data($fp);
}
while(count($rand)<$length and isset($info[‘timed_out’]) and !$info[‘timed_out’]);
fclose($fp);
}
echo implode(’,’,$rand);

mt_srand();
while(count($rand)<$length)
{
$rand[]=mt_rand(0,255);
}
return $rand;
}
[/php]

i try to get this to work for hours.
i’m thankfull for any ideas.
Q


#2

The $info array doesn’t get updated in your while() loop, so it’ll always have the same values.


#3

No I didn’t. I’m making random suggestions around here all the time.

If you would have given us more information about your issue, perhaps the code that you’ve been using so far that seems to be stuck in an infinite loop (because that’s what it sounds like), we may be able to actually help you out, perhaps in finding a solution, perhaps in finding a workaround.

Don’t assume I didn’t read your post. Maybe I didn’t understand what you meant, and your ambiguous choice of words isn’t making things clearer, but I did read it.


#4

sorry. i was just frustrated on that topic. i’ll remove that reply.

the code workes! no infinit loop.
as i made more research and i thing there is no solution.
u may prove me wrong.

to anwer the 3 questions i asked myself:

Is there a posibility in PHP

  • to read a file as stream
    NO! [edit: yes, use 2 scripts, one to read and echo the file, and one to read the other script]
  • or to specefy a timeout for reading files as it is with streams
    NO!
  • or a way to find out wether a file has data in it without EOF
    NO! [edit: YES, with stream_set_blocking() and srtlen()]

#5

Quite alright :slight_smile: I guess we’re all a little touchy (I know I am).

As for the questions, I really wouldn’t know :slight_smile: I just go with what I do and try to go from there. I’m pretty sure that php.net could answer those questions, and if not, google should come up with hits to people who encountered similar problems :slight_smile:


#6

both produced no results
thats why i was so frustrated.
and as i finaly got the same “not pobible” answers on irc i gave up.


#7

i hate people asking questions and never ever posting the solutions:

[edit: found a better one]
there is a easy solution to find out that a file is empty: stream_set_blocking($fp,0) and check the strlen() of the value returned by fgetc()/fgets()

final solution:
[php]
function Qrand($from,$to)
{
static $srand=false;
static $urand=true;
static $drand=true;
if($from>$to) return false;
if($from==$to) return $from;
$range=$to-$from+1;
if($drand and $drand=fopen(’/dev/random’,‘rb’) and stream_set_blocking($drand, 0))
{
for($i=1;$range>pow(256,$i-1)-1;$i++) $chars=$i;
$max=pow(256,$chars)-1;
$max-=$max%($range);
do
{
$rand=0;
$char=‘dummy’;
for($i=1;$i<=$chars and strlen($char);$i++)
{
if(strlen($char=fgetc($drand)))
$rand+=ord($char)*pow(256,$i-1);
}
}
while($rand>$max and strlen($char));
fclose($drand);
if(!strlen($char))$drand=false;
else return $rand%($range)+$from;
}
if($urand and $urand=fopen(’/dev/urandom’,‘rb’))
{
for($i=1;$range>pow(256,$i-1)-1;$i++) $chars=$i;
$max=pow(256,$chars)-1;
$max-=$max%($range);
do
{
$rand=0;
for($i=1;$i<=$chars;$i++)
$rand+=ord(fgetc($urand))*pow(256,$i-1);
}
while($rand>$max);
fclose($urand);
return $rand%($range)+$from;
}
if(!$srand)
{
mt_srand();
$srand=true;
}
return mt_rand($from,$to);
}
[/php]


#8

Is /dev/random such a strange file to read from then? And what exactly is the goal of the script? It kinda sounds like you need a random character/integer/something. Can’t you just pick one or two entries from /dev/random and use them as seeds for the rand() function in PHP? Not sure if this is what you’re looking for though.


#9

the problem of the buildin rand-functions is that they only support a seed up to 2.000.000.000 and i’m writing a Texas Holdem poker script. a poker deck has 8e67 (8*10^67) different ways of shuffling. if i use the buildin functions the winning-chance of the pocket-cards in that script would differ from the real once.

of cause i need a fall-back to the buildin functions but just for portability.

and yes /dev/random is that strange. it may be empty. in that case it isn’t reporing it, but waits till more entropy is collected, witch may take some seconds and may freeze the script especialy on reading more chars.


#10

Wow … taking the tough route eh?

If you define each card with an ID, you only need to be able to count to 52:

[php]
$dealtCards = array();

$nextCardToDeal = rand(1, 52);
while (in_array($nextCardToDeal, $dealtCards)) {
$nextCardToDeal = rand(1, 52);
}

$dealtCards[] = $nextCardToDeal;
[/php]

Keep track of each card that’s being dealt and make sure that the rand() function doesn’t pass out cards twice :slight_smile: Much easier than having to calculate EVERY possible deck, and nicer for your server’s resources too :slight_smile:


#11

always. :o

speed optimiasations are done later. :oops:
i’ll echo out the micro-time later. and if it is taking to much time i’ll cut it down to the realy used cards. :wink: :)


#12

8e67 -> 52 is not a speed optimization, it’s moving from hell to heaven, seriously. It would not only make your life THAT much easier, but also the next person’s who wants to use/read/adapt your code.

I’m currently doing my own PHP projects and won’t be touching your code anytime soon, though.


#13

it’s 52 to 9:
[php]
function randdeck()
{
global $nums2,$cols2;
$usedcards=array();
$deck=’’;
for($i=0;$i<52;$i++)
{
$rand=Qrand(0,51-$i);
sort($usedcards);
foreach($usedcards as $usedcard)
if($usedcard<=$rand)$rand++;
$usedcards[]=$rand;
$deck.=$nums2[$rand%13+1].$cols2[$rand%4];
}
return $deck;
}
[/php]


#14

i have done some editing. http://phphelp.com/forums/viewtopic.php?p=29222#29222
now there i got a good function for all those that need good random.
Qrand() is used the same way as rand(). no srand() needed.

done