PHP цикла цикла для извлечения из базы данных

1

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

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

спасибо

  • 0
    Поиск об отправленных сервером событиях
  • 0
    Можете ли вы поделиться как php, так и db подробностями?
Теги:
websocket

3 ответа

3
Лучший ответ

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

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

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

Лучшим местом для тайм-аута является socket_select(). В приведенном ниже коде будет ждать максимум 1 секунда для ввода новых пакетов, и когда вам станет скучно, это сделает ваш материал базы данных.

define("SOCKET_TIMEOUT", 1);

function tick() { /* Put your DB checking here. */ }

while (true) {
    $read = get_array_of_sockets_that_may_have_sent_a_packet();
    $write = $except = null; // We probably don't care about these.
    tick();
    $number_of_sockets_ready = socket_select($read, $write, $except, SOCKET_TIMEOUT);
    if ($number_of_sockets_ready === false) { ... } /* Something went horribly wrong. socket_strerror(socket_last_error()) is your friend here. */ 
    elseif ($number_of_sockets > 0) {
        // At least one socket is ready for socket_recv() or socket_read(). Do your magic here!
    }
}

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

  • 0
    Отлично работает, но проверяет наличие новых сообщений только для одного пользователя за раз. Я не могу найти решение для проверки базы данных для каждого подключенного пользователя.
  • 0
    @ michste93 socket_select() принимает массив дескрипторов сокетов в качестве аргументов и изменяет этот массив по ссылке. Когда socket_select() вернется, вы можете перебрать все дескрипторы сокета, оставленные в массиве.
Показать ещё 2 комментария
2

Мой предпочтительный метод - это простой вызов setTimeout() чтобы повторно проверять сервер на наличие новых сообщений.

var checkForNewMessages = window.setTimeOut(function(){
    $.ajax({
        url: 'getChatUpdates.php', 
        type: 'POST',
        data: {user_id: '<?php echo $_SESSION['user_id']; ?>' }
    }).done(function(r){
        // do stuff to display new messages here
    });
}, 5000);

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

В любом случае, теоретически, вы можете сгенерировать GUID со сценария на стороне сервера и передать его на ваш AJAX, а затем ajax использовать GUID в этом следующем вызове. GUID будет меняться с каждым вызовом таким образом, чтобы неавторизованный человек не смог просто дублировать этот запрос ajax.

Более простым методом может быть просто получить user_id с серверной стороны сеанса вместо передачи его в качестве параметра.

  • 0
    Хороший метод, но ваш пример очень рискованный (с user_id). Возможно, предоставьте свой ответ с некоторыми советами по безопасности или хотя бы предупреждением.
  • 0
    @ sanderbee, я вижу, что это ненужно, но я не понимаю, как это может быть так рискованно. Во всяком случае, обновил мой ответ.
Показать ещё 4 комментария
0

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

Архитектурно, это, вероятно, не самое изящное решение, так как вы также найдете, что люди спорят о том, что обсуждают аналогичный вопрос и смежное предложение здесь: Вызов скрипта PHP из триггера MySQL

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню