Long polling — как сделать уведомление?

Необходимо сделать уведомление о количестве новых сообщения для пользователей, используя Long polling.
Что есть на данный момент:

клиент 1
$(document).ready(function getmess(){
    $.ajax({
	url:"notif.php", 
	data:{"id":id},
	type:"POST",
	timeout: 10000,
        complete:getmess,
	success:function(result){
	$("#count").html(result);
	}
	});
});


сервер:
$mysqli = new mysqli('localhost', 'root', '', 'lc');
	if (mysqli_connect_errno()) { 
		printf("Подключение к серверу MySQL невозможно. Код ошибки: %s\n", mysqli_connect_error()); 
		exit; 
	}  
session_start(); 
	

$MY_ID = $_SESSION['id'];

$newData = false;

while (true) {
$result = $mysqli->query("SELECT COUNT(*) FROM messages WHERE user_get='$MY_ID' AND status='1' ");
if (mysqli_num_rows($result)) {
while ($row = mysqli_fetch_array($result)) {
echo $row[0]."";
}
flush();
exit;
}
sleep(5);
}


Реализацию данного метода подсмотрел по этой ссылке В чем ошибка при реализации Comet (Long — Polling) метода?
Суть в чем - мне надо отсылать запрос на сервер и ждать ответ 10 секунд, если ответа нет, то отсылать опять запрос и ждать 10 секунд ответа.

Но у меня никак не получается это сделать, - запросы отсылаются каждую секунду длиной тоже 1 секунду, при этом нарушается сам принцип Long polling. На изменения значения timeout не реагирует вообще.
  • Вопрос задан
  • 6672 просмотра
Пригласить эксперта
Ответы на вопрос 6
@mayorovp
А запрос через секунду прерывается - или же сервер что-то отвечает? Если сервер успешно отвечает - то надо и копаться в сервере, а не в клиенте.

Лично я вижу в серверном коде два подозрительных места.
1. Если в базе есть хоть одно сообщение, то оно будет выдаваться клиенту каждый раз. Нужно либо удалять его из базы - либо добавить в запрос какой-нибудь фильтр, чтобы отсечь уже прочитанное. Если поле id - автоинкремент, то можно фильтровать по нему.

2. Делать long pooling на связке "клиент-сервер" - и активных опрос на связке "сервер - база данных" - не лучший вариант. Надо вам поискать способ серверному скрипту так же уснуть до появления события, иначе весь long pooling непонятно зачем.
Ответ написан
@RageXL Автор вопроса
Нет запросы не прерываются, сервер отвечает. Просто длина запроса 1 секунда, а мне надо ждать ответа от сервера как минимум 10 секунд и в случае успешного ответа сразу отсылать новый запрос, так же если сервер не ответил в течении 10 секунд, т.е. в базе не было никаких изменений, то отсылать новый запрос длиной 10 секунд.
Мне нужно получать не сообщения а их число. Например в базу добавилось новое сообщение и число в блоке сразу увеличилось, т.е. просто уведомлять пользователя о новых сообщениях для него.
Ответ написан
nazarpc
@nazarpc
Open Source enthusiast
У вас есть сообщение в базе - вот они и возвращаются, вы же не проверяете полученные сообщение как прочитанные, вот у вас на запрос всегда срабатывает мгновенно. Как вариант можете отправлять на сервер предыдущее количество сообщений, и если оно не отличается от текущего - ждать. А ещё вам flush(); нафиг не нужен, в следующей же строчке exit; - всё равно буфер будет сброшен.
Ответ написан
Изначально выбрано неправильное направление.

Long polling + Сессии = зависание скриптов. Либо избавляйтесь от сессиий, либо от Long polling, либо используйте сторонние решения
Ответ написан
@RageXL Автор вопроса
Чего то я не пойму, как отослать на сервер уже имеющееся число сообщений ?
Допустим на странице есть такая выборка
$result = $mysqli->query("SELECT COUNT(*) FROM messages WHERE user_get='$MY_ID'");
		$row = $result->fetch_row();
		$totalm = $row[0]; // всего записей
	$result->close();


А как потом в тот же ajax скрипте реализовать отправку данных о количестве сообщений на php ?
Ответ написан
inside22
@inside22
Я бы на вашем месте установил на сервере NodeJS, он бы ежесекундно обращался к БД и проверял, есть ли новые записи или обновления для данного клиента или нет, если есть, то отсылал бы об этом информацию клиенту.

NodeJS позволяет держать соединение открытым, сервер при желании может засылать туда при нужде данные, а JS-код в браузере будет получать ответы и совершать нужные действия.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы