Foi assim que resolvi por enquanto, usando um arquivo.
Procedimento
- Obtenha o IP do cliente e faça um hash (para evitar a leitura do arquivo).
- Abra o arquivo IP e verifique cada linha
- Compare a hora do registro atual com a hora atual
- Se a diferença for maior que definir o tempo limite, vá para 5., senão 7.
- Se o IP corresponder ao cliente, crie um registro atualizado, senão
- descartar registro.
- Se o IP corresponder ao cliente, forneça uma mensagem de falha, caso contrário, copie o registro.
Código de exemplo
<?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);
?>
Observações
Novos usuários
Se o hash de IP não corresponder a nenhum registro, um novo registro será criado. Atenção:O acesso pode falhar se você não tiver direitos para fazer isso.
Memória
Se você espera muito tráfego, mude para uma solução de banco de dados como isto todos juntos.
Código redundante
"Mas minxomat", você pode dizer, "agora cada cliente percorre todo o arquivo!". Sim, de fato, e é assim que eu quero para minha solução. Desta forma, cada cliente é responsável pela limpeza de todo o arquivo. Mesmo assim, o impacto no desempenho é baixo, porque se cada cliente estiver limpando, o tamanho do arquivo será mantido no mínimo absoluto. Altere isso, se essa maneira não funcionar para você.