Я пишу приложение чата реального времени, используя websocket. У меня есть функция, которая проверяет базу данных для новых сообщений для конкретного пользователя. То, что я до сих пор не хватает, - это способ бесконечного вызова этого метода, чтобы пользователь мог получать сообщения в режиме реального времени.
Есть ли способ запустить фоновый цикл или что-то подобное, что может сделать трюк?
спасибо
Самое худшее, что вы могли бы сделать, - установить все ваши сокеты на неблокирующие. Это создаст цикл простоя, где ваш сервер 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()
снова будет вызван.
socket_select()
принимает массив дескрипторов сокетов в качестве аргументов и изменяет этот массив по ссылке. Когда socket_select()
вернется, вы можете перебрать все дескрипторы сокета, оставленные в массиве.
Мой предпочтительный метод - это простой вызов 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 с серверной стороны сеанса вместо передачи его в качестве параметра.
Я никогда не строил ничего подобного. Но как насчет написания обычного скрипта, который опроса базы данных, а затем толкает сообщения (я думаю, в идеале это должны быть отдельные компоненты) и настраивать запланированные задачи, которые запускают этот скрипт в желаемой вами частоте.
Архитектурно, это, вероятно, не самое изящное решение, так как вы также найдете, что люди спорят о том, что обсуждают аналогичный вопрос и смежное предложение здесь: Вызов скрипта PHP из триггера MySQL
Но, увидев, как вы задали свой вопрос, и что это значит о вашей настройке, это может начаться.