これが私が今のところファイルを使ってそれを解決した方法です。
手順
- クライアントIPを取得してハッシュします(ファイルの読み取りを防ぐため)。
- IPファイルを開き、各行をスキャンします
- 現在のレコードの時刻を現在の時刻と比較します
- 差が設定されたタイムアウトよりも大きい場合は5に進み、それ以外の場合は7に進みます。
- IPがクライアントと一致する場合は、更新されたレコードを作成します。それ以外の場合は
- ドロップレコード。
- IPがクライアントと一致する場合は失敗メッセージを提供し、そうでない場合はレコードをコピーします。
サンプルコード
<?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);
?>
備考
新規ユーザー
IPハッシュがどのレコードとも一致しない場合、新しいレコードが作成されます。重要:アクセスする権限がない場合、アクセスが失敗する可能性があります。
メモリ
多くのトラフィックが予想される場合は、これ すべて一緒に。
冗長コード
「しかし、minxomat」は、「各クライアントがファイル全体をループするようになりました!」と言うかもしれません。はい、確かに、それが私のソリューションに必要な方法です。このように、すべてのクライアントがファイル全体のクリーンアップを担当します。それでも、すべてのクライアントがクリーニングを実行している場合、ファイルサイズは最小限に抑えられるため、パフォーマンスへの影響は低く抑えられます。この方法でうまくいかない場合は、これを変更してください。