[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Еще раз про таймер на PHP
Dimaz
Приветствую. У меня уже была тема про то, как сделать таймер на PHP. Мне посоветовали записывать на сервере значение функции time() при загрузке страницы, и при отправке данных снова получать это значение и сверять разницу с тем, что было записано ранее.
Так же на мой вопрос ответили, что скорость интернета не может повлиять на точность результата.
Все так и сделал, на Денвере все работало без проблем. Но на днях я перенес свой проект на сервер в интернете. Так вот, работает не всегда как нужно. Периодически выскакивает ошибка "Неверное время". Значит все таки скорость и качество соединения влияет на точность результата. При том, что скорость у меня 4 мегабита и проблем с соединением почти не бывает. А что будет когда в проекте будут люди, нагрузка на сервер возрастет. Думаю тогда ошибка будет выскакивать постоянно. Как же тогда быть? Что еще можно придумать с таймером?
Вот моя тема: http://phpforum.ru/index.php?showtopic=71839
I++
Если не важна точность, можно записывать с упреждением.

Т.е логика такова:

1. Загрузка страницы с вопросом, на сервере записывается текущее функцией time()
2. На клиентской стороне ставим обратный отсчет таймера в 60 секунд. (максимальное время на ответ)
3. После ответа данные передаются на сервер, если за 60 секунд не успели срабатывается событие на клиентской стороне и отправляется запрос на сервер, что не пользователь не успел ответить.
4. На сервере в случае если пользователь ответил идет проверка записанного значения по принципу:

St - время сервера. (Записанное в базе, на начале теста)
Ct - текущее время.
Mt - максимальное время на ответ
It - погрешность.
Ft - флаг форсирования, сообщающий серверу о том, что клиент не успел за 60 секунд, и скрипт автоматически отправил серверу запрос говорящий о том, что пользователь опоздал.

Эксперемент 1 (Пользователь успел ответить в отведенные 60 секунд (Псевдокод)):

St = 100
Ct = 153
Mt = 60
It = 10
Ft = false

if(!Ft){
// Пользователь не успел ответить и клиент автоматически отправил запрос серверу.
}else if(Ct - St <= Mt){
// Да пользователь успел ответить за отведенное время Mt
}else{
// Нет пользователь не успел ответить за отведенное время Mt, используем проверку с погрешностью установленной в It
if(Ct - St <= Mt + It){
// Да пользователь успел ответить за отведенное время Mt c учетом погрешности It
}else{
// Нет пользователь не успел ответить за отведенное время Mt даже с учетом погрешности It. (Либо связь плохая, либо читер)
}
}


Для наглядности сделал так, а так можно просто на сервере Mt задать 70 секунд, а отсчет у клиента начинать с 60 секунд и не будет проблем со временем. Думаю если, кто подкрутить счетчик до 70 секунд, сильно обломается, потому что в эти 10 секунд будут заложены погрешности в передачи данных от сервера к клиенту и обратно, в зависимости от качества связи и производительности компьютера или тормозов сервера или клиента, время будет скакать в этих 10 секундах, кто-то управится за 0.2 сек, кто-то будет грузиться 4 сек, кто-то 8 сек (что мало вероятно) и проблема будет решена.

P.S

Зачем хранить время в базе? Лучше в сессии. В базу лишь результат записывать и данные о пользователе, ну ФИО там например и количество попугаев которые он набрал.
bestxp
фу какая мерзость

Делается просто

имеем
$salt = 'dfsdfsdf$ds';
$time = time();
записываем в форму где нужно следить за временем

<input hidden='timer' value = ".$time." />
<input hidden='timer_hash' value = ".md5($time.$salt)." />

а дальше при отправке проверяй уже время с контрольной суммой, правда это не защитит от обновления страницы
Dimaz
I++
Сейчас переварю все это)
Dimaz
Цитата (bestxp @ 3.03.2013 - 12:38)
фу какая мерзость

Делается просто

имеем
$salt = 'dfsdfsdf$ds';
$time = time();
записываем в форму где нужно следить за временем

<input hidden='timer' value = ".$time." />
<input hidden='timer_hash' value = ".md5($time.$salt)." />

а дальше при отправке проверяй уже время с контрольной суммой, правда это не защитит от обновления страницы

Не совсем понял. А как разницу потом высчитывать между полученным md5 и временем отправки данных на сервер?
И кстати на счет сессий. Что же все таки лучше, использовать сессии для хранения значения времени или лучше сохранять в БД? Хранить нужно такие данные как время, полученное функцией time(), идентификатор вопроса и количество секунд таймера.
I++
Цитата
Не совсем понял. А как разницу потом высчитывать между полученным md5 и временем отправки данных на сервер?


Это один из интересных способов можно назвать "ленивое хранение", инфу храним не в базе, а отдаем её пользователю, чтобы он её берег.

Смысл в том, что когда к нам придут переменные $_POST['timer'] и $_POST['timer_hash']
Делаем следующие:

<?php

$salt = 'dfsdfsdf$ds';
$time = time();
$maxtime = 60;

if($_POST['timer_hash'] == md5($_POST['timer'].$salt)){

if(($time - $_POST['timer']) < 60) {
echo 'Молодец ответил на вопрос, возьми сладкий рулет';
}else{
echo 'Не успел ответить ты на вопрос.';
}

}
else{
echo 'Зачем подделываешь таймер пёс смердящий?';
}


Цитата
И кстати на счет сессий. Что же все таки лучше, использовать сессии для хранения значения времени или лучше сохранять в БД? Хранить нужно такие данные как время, полученное функцией time(), идентификатор вопроса и количество секунд таймера.


Сессии удобнее и проще, чем целую базу создавать.

Тут в принципе 3 способа есть.

1. "Ленивое хранение" как в примере.
2. Сессии
3. СУБД различные ну или memcache.

Для мелких проектов сессии, для крупных субд или мемкеш. Крупный это когда по 10 тысяч в день будут тесты проходить пользователи, тогда сессии не актуальны.

Так, что для мелких я бы выбрал сессии для промежуточных данных, а результат теста можно и в базу записать.
Dimaz
Проект планируется крупный, свыше 10 тыщ уников в день.
Цитата
а результат теста можно и в базу записать.
Ну это само собой, иначе как потом юзер сможет посмотреть набранные баллы.
Т.е. лучше использовать базу.
Еще вопросик один. На моем сайте включена авторизация через Вконтакте. Пользователю сохраняются куки с его id-ом и вторая кука с уникальным ключом авторизации. Вот скрипт авторизации:
<?php
if(!isset($_COOKIE['auth_key'], $_COOKIE['viewer_id'])) {
$user_id = $_GET['viewer_id'];
$auth_key = $_GET['auth_key'];
if($user_id && $auth_key) {
include("config.php");
$real_auth_key = md5($api_id."_".$user_id."_".$api_key);
if($real_auth_key == $auth_key) {
setcookie("viewer_id", $user_id);
setcookie("auth_key", $auth_key);
}
else {
echo("Ошибка auth_key");
}
}

else {
echo("Неизвестная ошибка!");
}
}
else {include("user_auth.php");}
?>

В случае, если куки уже установлены подключается user_auth.php:
<?php
include_once("config.php");
$real_auth_key = md5($api_id."_".$_COOKIE['viewer_id']."_".$api_key);
if($real_auth_key != $_COOKIE['auth_key']) {
echo("auth_key error");
exit;
}
?>

Мне сказали на одном форуме, что нужно записать в страницу index.php такой код:
session_start();
$_SESSION["VK"] = $_GET;

Затем в других скриптах прописать:
session_start();
var_dump($_SESSION["VK"]);

Все это для того, чтобы не нужно было проходить авторизацию каждый раз при обращении к другим скриптам. Но у меня ничего не работает. Что не так?
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.