21.7. Случайные идентификаторы
Для того чтобы отслеживать, какое количество пользователей получают доступ к Web-узлу, вам потребуется присвоить им уникальные идентификаторы. Можно хранить любую информацию о данном пользователе в базе данных и передавать идентификатор со страницы на страницу с помощью ссылок или файлов cookie. Эти идентификаторы необходимо генерировать случайным образом; в противном случае под пользователя, имеющего право доступа, может замаскироваться любой желающий. К счастью, процесс создания случайных чисел несложен. Как он работает, показано в листинге 21.9. Задан набор символов, используемых для обозначения сеансов. В процессе создания идентификатора сеанса определенной длины символы выбираются случайным образом из списка. Этот идентификатор используется в ссылке, поэтому он будет передан на следующую страницу. Этот метод применили к любому браузеру, даже к браузеру Lynx. В главе 23, "Интеграция баз данных", обсуждается интеграция этого метода с базами данных.
Листинг 21.9. Генерирование идентификатора сеанса

<?php
// SessionID
// генерирует идентификатор сеанса function getSessionID($length=16)
{
// Задать набор допустимых символов $Pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $Pool .= "abcdefghijklmnopqrstuvwxyz"; $lastChar = strlen($Pool) - 1;
$sid = "";
for($i = 0; $i < $length;
{
$sid .= $Pool[mt_rand(0, $lastChar)];
}
return($sid);
}
// Задать генератору начальное значение mt_srand(100000000 * (double)microtime()); if(isset($_REQUEST['sid']))
{
print(" Идентификатор старого сеанса был {$_REQUEST['sid']}<br>n");
}
$sid = getSessionID();
print("<a href="{$_SERVER['PHP_SELF,]}?sid=$sid">"); print(" Получите новый идентификатор сеанса"); print("</a>n");
?>

 Здесь очень важно пользоваться случайными числами. Предположим, что для этого используются секунды и на протяжении целой секунды все идентификаторы сеанса будут одинаковы. А вероятность того, что на протяжении одной секунды к Web-узлу получат доступ много пользователей, очень высока. В листинге 21.8 для получения начального значения для генератора случайных чисел использовалось время в микро­секундах. Но даже в этом случае у нас будет определенное окно вероятности получения повторяющихся идентификаторов сеанса. Одним из способов обойти эту ситуацию является использование блокируемого ресурса, в котором будет храниться начальное значение, например в файле. Если один такой файл будет заблокирован, можно считать начальное значение и записать его в другой файл, и это даст полную гарантию того, что два параллельных процесса никогда не будут иметь одно и то же начальное значение. 

21.8. Выбор баннеров

Другой областью применения случайных чисел является выбор баннеров. Предположим, что у вашего Web-узла есть три спонсора. Каждый из них имеет по одному баннеру, которые будут поочередно демонстрироваться при доступе к Web-узлу. Для этого необходимо генерировать случайное число и поставить каждое число в соответствие определенному баннеру. В листинге 21.10 для вызова функции mt_rand использовался оператор switch. В таком случае о генерировании "хороших" начальных чисел беспокоиться не следует, необходимо лишь позаботиться о разумном распределении всех трех вариантов.

Сортировка, поиск и случайные числа