2011-08-24 2 views
6

Я пытаюсь написать простое приложение для веб-чата с PHP и AJAX.Отслеживание зарегистрированных пользователей в PHP

Мне нужно знать обо всех открытых сеансах, чтобы я мог отображать список онлайн-пользователей, с которыми можно поговорить. Мне также нужно знать о выходах журнала, потому что я использую «как отправку, так и принимающую сторону в автономном режиме» как условие для рассмотрения сеанса чата, завершенного и удаляющего сообщения.

Я отслеживаю вход в систему пользователей в базе данных: добавление записи при входе в систему и ее удаление при выходе из системы отлично работают, но это не является полным, так как есть два других способа, которыми пользователь может зарегистрироваться out:

  • Сессия на стороне сервера заканчивается после простоя.
  • клиентская сторона cookie уничтожается при закрытии браузера. Похоже, плохая идея использовать какой-то запущенный AJAX (что если браузер сбой или что-то?).

Простейшее решение, похоже, сохраняет временную метку последней активности. Я вижу некоторые проблемы с этим, хотя:

  • AFAIK стороне сервера экспирации шанс на основе, так что это не будет точным (и если я получаю время истечения 3 минут неправильно, это 3 минуты, где какой-то парень может быть разговаривая с пользователем в автономном режиме, задаваясь вопросом, почему никто не отвечает)
  • Мне пришлось бы постоянно запрашивать базу данных, чтобы проверять каждое зарегистрированное в последний раз время активности пользователей по сравнению с текущим временем. Я не вижу, когда/где я буду делать это эффективно. Кажется глупым делать это каждый раз, когда нужен список онлайн-пользователей.

Любая помощь оценивается. Я сам кодирую это, потому что я не знаю каких-либо веб-чат-фреймворков, которые могут интегрироваться с моей существующей пользовательской базой данных, поправьте меня, если я ошибаюсь.

+0

ОК, я понял, что на самом деле мне не нужно пытаться проверять метку времени. Поскольку каждый пользователь постоянно запрашивает проверку новых сообщений, я также могу обновлять временную метку каждый раз, когда идет запрос, и считать все временные метки> 20-секундными пользователями неактивными. Поэтому теперь мне просто нужно найти лучший способ для базы данных автоматически удалять записи со старыми отметками времени. – Jonathan

+0

@bfavaretto Большое спасибо за то, что заметили! программисты, кажется, правильное место, чтобы спросить, сделают. – Jonathan

ответ

0

Я не уверен, что если вам нужна как вероятность и делителя, но вот то, что я делаю для автоматического выхода из системы людей:

ini_set('session.gc_maxlifetime',3600); // 1 hour 
ini_set('session.gc_probability',1); // it does garbage cleaning EVERY time 
ini_set('session.gc_divisor',1); // it does garbage cleaning EVERY time 
session_start(); 
+0

Я понял, что это не проблема, см. Мой комментарий к OP. Однако нужно выяснить, как очистить старые записи, и я предпочел бы, чтобы очистка не запускалась каждый раз, когда пользователь запрашивает список онлайн-пользователей (кажется, что это отходы, он должен быть централизован и просто происходит на стороне сервера). – Jonathan

1

Я не думаю, что вы собираетесь быть в состоянии сделать много для уменьшения постоянных запросов, чтобы определить, вышли ли пользователи, закрыв браузер, проблемы с подключением к Интернету и т. д., но вы, возможно, могли бы каждый клиент сделать запрос AJAX на сервер каждые 5 секунд, чтобы обновить последнее время активности, и ваше приложение на сервере считает, что пользователь «вышел из системы», если они пропустили 3-4 последовательных запроса (т. е. их последнее время активности составляет> 20 секунд).

На стороне клиента вы можете проверить последнее время активности каждый раз, когда ваш клиент отправляет сообщение другому пользователю, и ответьте, что они вышли из системы, если это произошло. Если они попытаются открыть чат с другим пользователем, вы также можете сделать немедленный звонок, чтобы проверить их статус. Затем вы можете проверить статус всех пользователей в списке пользователей каждые 30 секунд. Таким образом, ваш клиент получает довольно быструю обратную связь, если человек (а), с которым он беседует, неожиданно отключается.

+0

Я согласен с первой частью, я думаю, было бы более эффективно, если бы база данных отслеживала устаревшие временные метки внутри, хотя бессмысленно иметь 10 пользователей в то же время, когда время очистки базы данных истекло. Должен ли я использовать cron + клиент mysql для этого или есть лучший способ? – Jonathan

+1

Cron отлично, но лучше запускать его через PHP-скрипт, который обращается к БД, таким образом вам будет легче, если вы захотите позже изменить поведение. – Ravi

+0

Я согласен с Ravi, cron + скрипт PHP - это путь сюда. Я предполагаю, что у вас есть доступ к crontab с тех пор, как вы спросили, но если по какой-то причине вы этого не сделаете, вы можете настроить функцию «бедный человек», которая будет отслеживать последний раз, когда была поставлена ​​задача выполняется и запускает его снова, если прошло $ x секунд, и ваш PHP-скрипт выполняет эту функцию для каждого запроса. Это боль, чтобы сделать, и не так точно, поскольку вы не можете точно гарантировать, когда задача будет выполнена, но она работает в крайнем случае. Я должен был сделать это раньше, когда у меня не было доступа к crontab ... –

0

Большинство данных, которые вы в настоящее время используете, и данные, которые вам нужны, хранятся в сеансе PHP - просто не ясно, как получить идентификатор пользователя из информации.

Если вы переключитесь на использование обработчика сеанса с привязкой к базе данных, все становится очень легко. У меня был быстрый google - и есть много примеров. но многие из них (например,this one) не проверяйте срок действия при чтении сеанса. OTOH в примере, к которому я привязался, показывает добавление идентификатора пользователя в запись сеанса - что вам понадобится позже. Поэтому сеанс чтения функция обработчика должна быть что-то вроде:

read: 
SELECT session_data, username 
FROM sessions 
WHERE session_id=' . session_id() . ' 
AND last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime')) 

И чтобы получить все в настоящее время зарегистрированных пользователей:

SELECT username 
FROM sessions 
WHERE last_updated>= ' . date('YmdHis', time()-ini_get('session.gc_maxlifetime')) 

... и пусть (переопределены) сеанса сборщик мусора автоматически очистить избыточные данные.

HTH

0

Сначала отделите ваши вопросы. Что касается «списка онлайн-пользователей», вы можете использовать базу данных &, похоже, вы уже поняли это. (даже если кто-то не выйдет из строя должным образом, отображение нескольких дополнительных пользователей в Интернете не наносит большого ущерба)

Теперь для приложения чата, для проверки того, что пользователь все еще находится в сети, вам нужно будет использовать ajax. Просто нет другого пути. Конечно, всегда может быть взлома, я не знаю. см. Изображение image, когда вы отвечаете здесь (stackoverflow) .it постоянно проверяет, прошло ли время (& вы написали что-нибудь новое) & сохраняет копию.

1

Вы можете инвертировать свой шаблон, заменив поведение Ajax pull на систему push-уведомлений.

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

Это немного сложнее, чем способ потянуть ajax, но как только будет реализована основная структура, вы можете легко добавить функциональность, и производительность будет намного лучше.

Некоторые ссылки я обнаружил, что может быть полезно:

Это railscast эпизод, иметь дело с яваскрипта чата, реализация в рельсах, но даже если вы не понимаете рельсы, вы должны следовать им, чтобы получить основные понятия: http://railscasts.com/episodes/260-messaging-with-faye

+0

Спасибо за этот ответ. Я не знал о существовании рамок для уведомлений для JS, поэтому теперь у меня есть что-то новое, с чем мне нужно познакомиться. :-) –

+0

Из моей лиги на данный момент, но я тоже не знал об этом, я всегда считал, что не хватает толчка AJAX. Замечательно знать. – Jonathan

0

Кажется, что вас больше всего волнует производительность, и вы выяснили детали реализации (в основном). Просто измените тип таблицы, которая обрабатывает сеансы в «память», это снизит стоимость выполнения запроса db для каждого запроса почти ничего, поскольку вы извлекаете данные непосредственно из ОЗУ. Просто убедитесь, что вы удаляете сеанс каждый раз, когда вызывается пользовательская ошибка, или вы отмечаете пользователя как неактивный.

Но независимо от того, что вы реализуете, что-то, что требует постоянной связи между клиентом и сервером, никогда не может быть выполнено по HTTP. Но если вы установите разумные тайм-ауты и т. Д., Он будет работать в 99% случаев.

0

Я опоздал на эту вечеринку, но позвольте мне дать мои два цента.

В этом конкретном случае нет необходимости в системе push для плохих уведомлений.Также нет необходимости в cron. Позвольте мне объяснить:

Скажите A, B и C в чате. & Браузер B отпадает, поэтому его сеанс истекает. Прямо сейчас, сервер думает, что B все еще там, но она нет. Как вы обновляете A & C? Когда A & C СПРОСИТЕ для обновления. Проверьте последнюю временную метку B и выясните, что срок ее сессии истек.

Если все A, B & C аварии, тогда этого никогда не бывает. Я слышу, что вы спрашиваете. Какая разница? Теперь некому увидеть нашу ошибку! Единственный недостаток - поддерживать живую комнату в чате, которая стоит в пространстве базы данных. Это можно очистить, когда будет создан другой сеанс чата.

Заключительная Суть:

  1. Держите метки времени в последний раз было принято действие.
  2. Используйте событие пользователя, чтобы прокрутить отметки времени и вынуть мертвую древесину.

В случае пользователей это приведет к их регистрации. В случае чатов, это будут те, которые истекли.

Смежные вопросы