Подтвердить что ты не робот

Как я могу проверить в реальном времени, если пользователь вошел в систему?

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

В настоящее время я создаю эту функцию, устанавливая функцию интервала со стороны клиента, которая создает файл с именем: userId.txt

В области администрирования я создал функцию интервала, которая проверяет, существует ли userId.txt. Если он существует, он удаляет его. Если файл не воссоздается функцией пользовательского интервала - в следующий раз, когда функция администратора обнаружит, что файл отсутствует, он помечает клиента этим userId как неактивным.

Абстрактное представление:

customer -> interval Ajax function -> php [if no file - create a new file]
admin -> interval Ajax function -> php [if file exists - delete the file] -> return state to Ajax function and do something

Мне было интересно, есть ли лучший способ реализовать эту функцию, о которой вы можете думать?

4b9b3361

Ответ 1

Мое решение - использовать jquery ready и beforeunload для запуска запроса ajax post, который будет уведомлять пользователя о прибытии и выходе пользователя. Это решение является "легким", потому что оно регистрируется только дважды для каждого пользователя.

support.html

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>

//log user that just arrived - Page loaded
$(document).ready(function() {
         $.ajax({
        type: 'POST',
        url: 'log.php',
        async:false,
        data: {userlog:"userid arrived"}
    });
});

//log user that is about to leave - window/tab will be closed.
$(window).bind('beforeunload', function(){
    $.ajax({
        type: 'POST',
        url: 'log.php',
        async:false,
        data: {userlog:"userid left"}
    });
});
</script>
</head>
<body>

<h2>Your support html code...</h2>

</body>
</html>

log.php

<?php

//code this script in a way that you get notified in real time
//in this case, I just log to a txt file

$userLog = $_POST['userlog'];
file_put_contents("userlog.txt", $userLog."\n", FILE_APPEND );
//userid arrived
//userid left

Примечания:

1 - Проверено на Chrome, FF и Opera. У меня нет mac, поэтому я не мог проверить его на Safari, но он тоже должен работать.
2 - Я пробовал метод unload, но он был не таким надежным, как beforeunload.
3 - Установка async в false в запросе ajax означает, что оператор, который вы вызываете, должен завершиться до следующего оператора, это гарантирует, что вы получите уведомление до закрытия окна/вкладки.

Ответ 2

@Gonzalon делает хорошую точку, но с использованием обычной таблицы DB или файловой системы для постоянного обновления движения пользователя будет исчерпывающим для большинства жестких дисков. Это было бы хорошей причиной для использования разделяемой памяти в PHP.

Ответ 3

Вы должны различать бит между исходным вопросом "Как проверить в режиме реального времени, если пользователь вошел в систему?" и "Как я могу убедиться, если пользователь все еще находится на другой стороне (в моем чате)?".

Для "системы входа" я предлагаю работать с сеансами PHP.

В вопросе "все еще есть пользователь" я предлагаю обновить одно поле активного сеанса с именем LAST_ACTIVITY. Необходимо записать временную метку с последним контактом с клиентом в хранилище (базу данных) и проверить, является ли это старше X секунд.

Я предлагаю сеансы, потому что вы не упомянули их в своем вопросе, и похоже, что вы создаете файл userID.txt вручную для каждого запроса Ajax, правильно? Это не нужно, если рабочие cookie и сеансы не являются требованиями к разработке.

Теперь, для сессий PHP, я просто изменил бы обработчик сеанса (бэкэнд) на любые масштабы для вас и упростил бы запрашивающую информацию. По умолчанию PHP использует временную папку сеанса для создания файлов сеанса, но вы можете изменить его, так что основной обработчик сеанса станет базой данных mariadb или memcache или rediska.

Когда сеансы пользователей хранятся в базе данных, вы можете запросить их: "Сколько пользователей теперь зарегистрировано?", "Кто есть где?".

Ответ на вопрос "Как я могу проверить в реальном времени, если пользователь вошел в систему?" когда пользовательский сеанс создается и пользователь успешно аутентифицирован.


Для приложения чата реального времени существует множество технологий: от "php comet", "html5 eventsource" + "websockets" / "длительный опрос" до "очередей сообщений", таких как RabbitMq/ActiveMq с публикацией/подписаться на определенные каналы.

Если это простая или ограниченная среда, возможно, VPS, вы можете по-прежнему придерживаться своего решения интервальных запросов Ajax. Затем каждый запрос может обновить $_SESSION['LAST_ACTIVITY'] с помощью временной метки сервера. Ссылка: fooobar.com/questions/11386/...

Модификацией этой идеи было бы прекращение выполнения Ajax-запросов, когда движение мыши прекращается. Если пользователь не перемещает мышь на вашу страницу за 10 минут, вы перестанете обновлять метку времени LAST_ACTIVITY. Это позволит устранить проблему, показывающую пользователей, которые не работают в режиме онлайн.

Другая модификация - уменьшить размер "iam still here" REQUEST для сервера, используя небольшие запросы GET или HEADER. Короткий HEADER "ping" достаточно часто, вместо отправки длинных сообщений или JSON через POST.

Здесь вы можете найти полное "Как создать Ajax-веб-чат с PHP, jQuery". Они используют тайм-аут в течение 15 секунд для чата.

Ответ 4

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

Вам было бы намного лучше использовать решение NoSQL, такое как Redis, для любых действий, которые вам нужно выполнять часто (например: "он-лайн", проверки краткосрочных обновлений разговора и проверки обновлений разговоров через короткие промежутки времени).

Затем вы будете использовать базу данных для выполнения более длительных задач, таких как сохранение пользовательской информации и сохранение активных разговоров через определенные промежутки времени (например, один раз в минуту).

Ответ 5

Почему Ajax, а не Websockets? Разумеется, websocket предоставит вам значительно более быструю чат-систему, не потребует генерации и проверки текстового файла, не будет включать поиск базы данных, и вы можете сразу сказать, отключено ли соединение.

Ответ 6

Я бы установил библиотеку https://github.com/nrk/predis. Таким образом, в момент аутентификации пользователя он публикует сообщение на сервере Redis.

Затем вы можете настроить небольшой сервер node на back-end - что-то простое:

var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var redis = new Redis();

var authenticatedUsers = [];

// Subscribe to the authenticatedUsers channel in Redis
redis.subscribe('authenticatedUsers');

// Logic for what to do when a message is received from Redis
redis.on('message', function(channel, message) {
  authenticatedUsers.push(message);
  io.emit('userAuthenticated', message);
});

// What happens when a client connects
io.on('connection', function(socket) {
  console.log('connection', socket.id);

  socket.on('disconnect', function(a) {
    console.log('user disconnected', a);
  });
});

server.listen(3000);

Далеко не полный, но что-то, чтобы вы начали.

В качестве альтернативы, взгляните на Firebase. https://www.firebase.com/, если вы не хотите беспокоиться о стороне сервера

Ответ 7

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

Это поможет нам быть эффективными и быстрыми, чтобы узнать, находится ли пользователь в сети. Всякий раз, когда пользователь перемещает мышь или нажимает клавиши, обновляйте сеансовое хранилище с датой и временем. Периодически проверяйте его, нет ли пустого или нулевого, и решите, что пользователь покинул сайт.

Ответ 8

Вместо создания и удаления файлов вы можете сделать то же самое с преимуществами cookie использования cookie

  • Вам не нужно удалять запрос ajax для создания файла на сервере, поскольку файлы cookie доступны javascript/jquery.
  • Cookies имеют возможность установить временной интервал, поэтому автоматически удалят себя через некоторое время, поэтому вам не понадобится php script, чтобы удалить это.
  • Файлы cookie доступны через php, поэтому, когда вам нужно проверить, активен ли пользователь, нет, вы можете просто проверить, существует ли файл cookie

Ответ 9

В зависимости от ваших ресурсов вы можете выбрать websockets или предыдущий метод с именем long pool request. Оба обеспечивают двунаправленную связь между сервером и клиентом. Но они могут быть дорогими на ресурсах.

Вот хороший учебник по websocket:

http://www.binarytides.com/websockets-php-tutorial/

Ответ 10

Я бы использовал обратный вызов, который вы можете вызвать (admin). Я использую эту технику в веб-приложении и мобильных приложениях (все это задано на стороне пользователя с сервера):

  • Отправьте сообщение пользователю (например: "behave или я запрещаю вам" ).
  • Обновить статус/местоположение пользователя. (для событий, которые нужно знать, когда обслуживающий персонал прибывает).
  • Завершить подключение пользователя (например, выйти из системы в случае обслуживания).
  • Задайте время отчета пользователя (например, как часто пользователь должен отчитываться)

Обратный вызов для веб-приложения обычно находится в JavaScript, и вы определяете, когда и как вы хотите, чтобы пользователь звонил домой. Подумайте об этом как о канале обслуживания.

Ответ 11

Если бы это был aspnet, я бы сказал signalR... но для php, возможно, вы могли бы заглянуть в Rachet, это могло бы помочь с большим количеством того, что вы пытаетесь выполнить, поскольку сообщения могут быть отправлены клиентам вместо опроса клиентов.

Ответ 12

Imo, нет необходимости в настройке решений с двунаправленной связью. Вы хотите знать только, был ли пользователь еще включен или подключен к системе. Если я правильно понимаю, вам нужно только сообщение от сервера к клиенту. Поэтому вы можете попробовать SSE (события, отправленные сервером). Ссылка дает вам представление о том, как реализовать это с помощью PHP.

Идея проста. Сервер знает, подключен ли пользователь или нет. Он мог отправить что-то вроде "эй, пользователь xyz все еще зарегистрирован" или "эй, пользователь xzy, похоже, больше не регистрируется", и клиент только слушает эти сообщения и может реагировать на сообщения (например, через JavaScript).

Преимущество: SSE действительно хорош для приложений реального времени, потому что сервер должен отправлять данные только клиенту, а также читать спецификацию для этого.

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

Ниже приведено последнее обновление с приятным примером чата (написанным на Java). Вероятно, также хорошо понять, как реализовать это в PHP.