Это проще, чем я думал вначале. По сути, у вас есть страница, которая ничего не делает, пока не будут доступны данные, которые вы хотите отправить (скажем, приходит новое сообщение).
Вот действительно простой пример, который отправляет простую строку через 2-10 секунд. 1 к 3 вероятность возврата ошибки 404 (чтобы показать обработку ошибок в следующем примере Javascript)
msgsrv.php
<?php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
Примечание: на реальном сайте запуск этого на обычном веб-сервере, таком как Apache, быстро свяжет все «рабочие потоки» и не сможет отвечать на другие запросы. Есть способы обойти это, но рекомендуется писать «сервер длинных опросов» в чем-то вроде витого Python , который не зависит от одного потока на запрос. CometD является популярным (доступен на нескольких языках), а Tornado - это новый фреймворк, созданный специально для таких задач (он был создан для длинного кода FriendFeed) ... но в качестве простого примера, Apache более чем адекватен ! Этот скрипт легко может быть написан на любом языке (я выбрал Apache / PHP, так как они очень распространены, и мне довелось запускать их локально)
Затем в Javascript вы запрашиваете вышеуказанный файл ( msg_srv.php
) и ждете ответа. Когда вы получаете один, вы действуете на основе данных. Затем вы запрашиваете файл и ждете снова, воздействуете на данные (и повторяете)
Ниже приведен пример такой страницы. Когда страница загружается, она отправляет начальный запрос msgsrv.php
файла. Если это удается, мы добавляем сообщение в #messages
div, затем через 1 секунду мы снова вызываем функцию waitForMsg, который вызывает ожидание.
1 секунда setTimeout()
- это действительно простой ограничитель скорости, без него он работает нормально, но если он msgsrv.php
всегда возвращается мгновенно (например, с синтаксической ошибкой), вы загружаете браузер и он может быстро зависнуть. Это лучше сделать, проверяя, содержит ли файл правильный ответ JSON, и / или сохраняя общее количество запросов в минуту / секунду, и соответствующим образом останавливая.
Если страница ошибается, она добавляет ошибку в #messages
div, ждет 15 секунд, а затем пытается снова (идентично тому, как мы ждем 1 секунду после каждого сообщения)
Преимущество этого подхода в том, что он очень устойчивый. Если клиентское интернет-соединение прекратит работу, оно истечет время ожидания, затем попытайтесь подключиться снова - это присуще тому, как долго работает опрос, не требуется сложной обработки ошибок
В любом случае, long_poller.htm
код, используя фреймворк jQuery:
<html>
<head>
<title>BargePoller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
body{ background:#000;color:#fff;font-size:.9em; }
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.old{ background-color:#246499;}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
<script type="text/javascript" charset="utf-8">
function addmsg(type, msg){
/* Simple helper to add a div.
type is the name of a CSS class (old/new/error).
msg is the contents of the div */
$("#messages").append(
"<div class='msg "+ type +"'>"+ msg +"</div>"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "msgsrv.php",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data){ /* called when request to barge.php completes */
addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg, /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
addmsg("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg, /* Try again after.. */
15000); /* milliseconds (15seconds) */
}
});
};
$(document).ready(function(){
waitForMsg(); /* Start the inital request */
});
</script>
</head>
<body>
<div id="messages">
<div class="msg old">
BargePoll message requester!
</div>
</div>
</body>
</html>