Dit is hoe ik het voor nu heb opgelost, met behulp van een bestand.
Procedure
- Verkrijg het IP-adres van de klant en hash het (om het uitlezen van bestanden te voorkomen).
- Open IP-bestand en scan elke regel
- Vergelijk de tijd van het huidige record met de huidige tijd
- Als het verschil groter is dan de ingestelde time-out, ga dan naar 5., anders 7.
- Als IP overeenkomt met client, maak bijgewerkte record aan, anders
- record laten vallen.
- Als het IP-adres overeenkomt met de client, geef dan een foutbericht op, anders kopieer je het record.
Voorbeeldcode
<?php
$sIPHash = md5($_SERVER[REMOTE_ADDR]);
$iSecDelay = 10;
$sPath = "bucket.cache";
$bReqAllow = false;
$iWait = -1;
$sContent = "";
if ($nFileHandle = fopen($sPath, "c+")) {
flock($nFileHandle, LOCK_EX);
$iCurLine = 0;
while (($sCurLine = fgets($nFileHandle, 4096)) !== FALSE) {
$iCurLine++;
$bIsIPRec = strpos($sCurLine, $sIPHash);
$iLastReq = strtok($sCurLine, '|');
// this record expired anyway:
if ( (time() - $iLastReq) > $iSecDelay ) {
// is it also our IP?
if ($bIsIPRec !== FALSE) {
$sContent .= time()."|".$sIPHash.PHP_EOL;
$bReqAllow = true;
}
} else {
if ($bIsIPRec !== FALSE) $iWait = ($iSecDelay-(time()-$iLastReq));
$sContent .= $sCurLine.PHP_EOL;
}
}
}
if ($iWait == -1 && $bReqAllow == false) {
// no record yet, create one
$sContent .= time()."|".$sIPHash.PHP_EOL;
echo "Request from new user successful!";
} elseif ($bReqAllow == true) {
echo "Request from old user successful!";
} else {
echo "Request failed! Wait " . $iWait . " seconds!";
}
ftruncate($nFileHandle, 0);
rewind($nFileHandle);
fwrite($nFileHandle, $sContent);
flock($nFileHandle, LOCK_UN);
fclose($nFileHandle);
?>
Opmerkingen
Nieuwe gebruikers
Als de IP-hash met geen enkele record overeenkomt, wordt een nieuwe record gemaakt. Let op:toegang kan mislukken als u geen rechten heeft om dat te doen.
Geheugen
Als u veel verkeer verwacht, schakel dan over naar een database-oplossing zoals dit allemaal samen.
Overtollige code
"Maar minxomat", zou je kunnen zeggen, "nu doorloopt elke client het hele bestand!". Ja, inderdaad, en zo wil ik het ook voor mijn oplossing. Zo is elke klant verantwoordelijk voor het opschonen van het hele dossier. Toch blijft de impact op de prestaties laag, want als elke klant aan het opschonen is, wordt de bestandsgrootte tot het absolute minimum beperkt. Wijzig dit als deze manier niet voor u werkt.