Как реализовать базовый длинный опрос?

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

Все, что я могу найти, - это cometd, который использует структуру Dojo JS и довольно сложный сервер. система..

В принципе, как мне использовать Apache для обслуживания запросов и как написать простой скрипт (скажем, на PHP), который будет «долго опрашивать» сервер на предмет новых сообщений?

Пример не обязательно должен быть масштабируемым, безопасным или полным, он просто должен работать!


person dbr    schedule 02.12.2008    source источник


Ответы (17)


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

Вот действительно простой пример, который отправляет простую строку через 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 always возвращает мгновенно (например, с синтаксической ошибкой) - вы заливаете браузер, и он может быстро зависнуть вверх. Это было бы лучше сделать, проверив, содержит ли файл действительный ответ 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>
person dbr    schedule 02.12.2008
comment
Не могли ли проскользнуть некоторые сообщения с использованием этой идеи? За этот 1-секундный тайм-аут, скажем, было отправлено 1000 сообщений чата, как сервер узнает, что нужно отправить 1000 сообщений именно этому клиенту? - person DevDevDev; 07.10.2009
comment
Наверное. Это очень упрощенный пример, демонстрирующий концепцию. Чтобы сделать это лучше, вам понадобится более сложный серверный код, где он будет хранить эти 1000 сообщений для этого конкретного клиента и отправлять их одним блоком. Вы также можете безопасно уменьшить время ожидания waitForMsg - person dbr; 07.10.2009
comment
отличное решение. Работает прямо из коробки. Кажется, здесь я отвечу на мой вопрос: stackoverflow.com/questions/3002213/. Отличная работа. - person David Dombrowsky; 31.08.2010
comment
nodejs - еще одно отличное решение на стороне сервера для длинных запросов на опрос с дополнительным преимуществом (по сравнению с Twisted), которое вы можете написать код сервера тоже в Javascript. - person Husky; 25.02.2011
comment
Разве этот пример не открывает новое соединение для каждого waitForMsg ()? - person Deele; 05.05.2011
comment
Это просто повторяющиеся AJAX-подключения к серверу с интервалом в 1 секунду. Это не имеет ничего общего с длительным опросом. Длительный опрос должен поддерживать соединение, пока истекает время ожидания клиента. - person Deele; 05.05.2011
comment
@Delee, почему бы тебе просто не опубликовать свое решение? - person jaym; 02.08.2011
comment
@Delee Вы ошибаетесь. Тайм-аут в 1 секунду устанавливается только после успешного завершения запроса на длительный опрос, если запрос на длительный опрос не завершается, он истекает через 50 секунд. - person Brandon; 29.08.2011
comment
вопрос в том, что делает настоящий PHP-скрипт вместо sleep(rand(2,10));? чтобы ничего не делать, опрашивать базу данных каждые 100 миллисеков? когда он решает умереть? - person Luis Siquot; 28.09.2011
comment
Мне любопытно, может ли Apache Tomcat обрабатывать этот длинный опрос или, как и Apache, он также связывает сервер с большим количеством запросов? Любые идеи по этому поводу. - person Balkrishan Nagpal; 02.04.2012
comment
@Bala без понятия, возможно, стоит отдельный вопрос, хотя эта ветка форума подразумевает, что у нее есть ограничение на количество рабочих потоков. - person dbr; 02.04.2012
comment
Ранее я применял подобную технику на своем форуме - js запрашивает файл php на сервере, который затем циклически проверяет наличие новых сообщений в течение максимум 30 секунд, а затем возвращает либо false, либо новые сообщения. Затем JS обрабатывает ответ и отправляет другой запрос. Он работает нормально, но, похоже, сильно замедляет работу браузера, когда я покидаю страницу, если был ожидающий запрос ... Почему это? На мой взгляд, браузер просто запросит следующую страницу, и PHP завершит работу и затем отправит свой ответ, но его никто не получит. Почему он замедляется? Как я мог это исправить? - person Sean Bone; 01.08.2012
comment
Уловка, позволяющая избежать пропущенных сообщений, состоит в том, чтобы включить Id или TimeStamp последнего сообщения, полученного клиентом, в запрос AJAX - таким образом, сервер может легко вернуть все сообщения, начиная с [Blah]. - person Basic; 13.04.2013
comment
Итак, я предполагаю, что меня смущает, хотя в функции успеха и ошибки запрос ajax перезапускается, поэтому разве не создается новое http-соединение для каждого запроса ajax? - person Rooster; 18.06.2013
comment
@Rooster Правильно, для каждого он создает отдельный HTTP-запрос. Это похоже на долгий опрос, а не на повторное использование одного соединения. Похоже, вы ищете что-то вроде многостраничной потоковой передачи HTTP, веб-сокетов и т. Д. - person dbr; 19.06.2013
comment
Чем это так отличается от выполнения setInterval () каждые X секунд и загрузки данных таким образом? В любом случае тот или иной сценарий считывает и отправляет данные с сервера каждые X секунд. - person Chud37; 24.07.2013
comment
@ Chud37 Аналогично, но с меньшей задержкой. Соединение с длительным опросом получает данные, как только они становятся доступными, тогда как при опросе setInterval каждые 5 секунд данные могут стать доступными через 1 секунду, но у вас есть 4-секундный промежуток, прежде чем они станут видимыми. - person dbr; 25.07.2013
comment
очень капот спасибо! это спасло мне день! - person ; 31.12.2019

У меня есть очень простой пример чата как часть slosh.

Изменить: (поскольку каждый вставляет сюда свой код)

Это полноценный многопользовательский чат на основе JSON с использованием длинного опроса и slosh. Это демонстрация того, как выполнять вызовы, поэтому не обращайте внимания на проблемы XSS. Никто не должен развертывать это без предварительной дезинфекции.

Обратите внимание, что у клиента всегда есть соединение с сервером, и как только кто-нибудь отправит сообщение, все сразу же увидят его.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2008 Dustin Sallings <[email protected]> -->
<html lang="en">
  <head>
    <title>slosh chat</title>
    <script type="text/javascript"
      src="http://code.jquery.com/jquery-latest.js"></script>
    <link title="Default" rel="stylesheet" media="screen" href="style.css" />
  </head>

  <body>
    <h1>Welcome to Slosh Chat</h1>

    <div id="messages">
      <div>
        <span class="from">First!:</span>
        <span class="msg">Welcome to chat. Please don't hurt each other.</span>
      </div>
    </div>

    <form method="post" action="#">
      <div>Nick: <input id='from' type="text" name="from"/></div>
      <div>Message:</div>
      <div><textarea id='msg' name="msg"></textarea></div>
      <div><input type="submit" value="Say it" id="submit"/></div>
    </form>

    <script type="text/javascript">
      function gotData(json, st) {
        var msgs=$('#messages');
        $.each(json.res, function(idx, p) {
          var from = p.from[0]
          var msg = p.msg[0]
          msgs.append("<div><span class='from'>" + from + ":</span>" +
            " <span class='msg'>" + msg + "</span></div>");
        });
        // The jQuery wrapped msgs above does not work here.
        var msgs=document.getElementById("messages");
        msgs.scrollTop = msgs.scrollHeight;
      }

      function getNewComments() {
        $.getJSON('/topics/chat.json', gotData);
      }

      $(document).ready(function() {
        $(document).ajaxStop(getNewComments);
        $("form").submit(function() {
          $.post('/topics/chat', $('form').serialize());
          return false;
        });
        getNewComments();
      });
    </script>
  </body>
</html>
person Dustin    schedule 03.12.2008
comment
Могу я узнать, как это всегда связано? Извините, если я спрашиваю что-то глупое, но я хочу это знать. - person Rocky Singh; 23.01.2011
comment
Он выполняет HTTP GET, и сервер блокирует GET до тех пор, пока не станут доступны данные. Когда данные поступают на сервер, сервер возвращает данные клиенту, ставит в очередь все, что может поступить, а затем клиент повторно подключается и забирает отсутствующие сообщения, если таковые имеются, в противном случае он снова блокируется. - person Dustin; 23.01.2011
comment
Сначала это может быть неочевидно, но дело в том, что за «всегда подключенное состояние» отвечает ajaxStop с getNewComments там обратный вызов, поэтому он просто запускает его в конце каждого запроса ajax бесконечно - person baldrs; 20.01.2016

Tornado разработан для длительного опроса и включает очень минимальный (несколько сотен строк Python) chat app в / examples / chatdemo, включая код сервера и код клиента JS. Работает это так:

  • Клиенты используют JS для запроса обновлений с (номер последнего сообщения), сервер URLHandler получает их и добавляет обратный вызов для ответа клиенту в очередь.

  • Когда сервер получает новое сообщение, срабатывает событие onmessage, проходит через обратные вызовы и отправляет сообщения.

  • Клиентский JS получает сообщение, добавляет его на страницу, а затем запрашивает обновления с этого нового идентификатора сообщения.

person mikemaccana    schedule 04.03.2011

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

Тогда сервер выглядит так.

while (!hasNewData())
    usleep(50);

outputNewData();

Итак, запрос AJAX отправляется на сервер, вероятно, включая метку времени последнего обновления, чтобы ваш hasNewData() знал, какие данные у вас уже есть. Затем сервер находится в спящем цикле до тех пор, пока не станут доступны новые данные. Все это время ваш запрос AJAX все еще подключен, просто зависает в ожидании данных. Наконец, когда доступны новые данные, сервер передает их вашему запросу AJAX и закрывает соединение.

person Greg    schedule 02.12.2008
comment
Это занятое ожидание, которое блокирует ваш текущий поток. Это совсем не масштабируется. - person Wouter Lievens; 24.09.2009
comment
Нет, усон - это не занятое ожидание. И весь смысл ожидания в том, чтобы на время заблокировать ваш поток. Вероятно, он имел в виду 50 миллисекунд (usleep (50000)), а не 50 микросекунд! Но в любом случае, при типичной настройке Apache / PHP, есть ли какой-либо другой способ сделать это? - person Matt; 28.11.2011
comment
Ну, из принципа, вы не можете сделать функцию блокировки сообщения чата без ожидания. - person Tomáš Zato - Reinstate Monica; 27.11.2013
comment
Действительно здорово! Я создал рекурсивную функцию на сервере для проверки новых данных. Но какой продукт лучше всего подходит для эффективного использования длительного опроса? Я использую обычный Apache, и сервер не отвечает, когда я открываю более 4/5 вкладок браузера :( Ищу что-то для использования с PHP - person moderns; 07.05.2014

Вот несколько классов, которые я использую для длительного опроса в C #. Всего существует 6 классов (см. Ниже).

  1. Контроллер: обрабатывает действия, необходимые для создания допустимого ответа (операции с базой данных и т. д.).
  2. Процессор: управляет асинхронным взаимодействием с веб-страницей (самой собой).
  3. IAsynchProcessor: служба обрабатывает экземпляры, реализующие этот интерфейс.
  4. Служба: обрабатывает объекты запроса, реализующие IAsynchProcessor.
  5. Запрос: оболочка IAsynchProcessor, содержащая ваш ответ (объект).
  6. Ответ: содержит настраиваемые объекты или поля.
person Prisoner ZERO    schedule 01.09.2011
comment
Хорошо ... так ПОЧЕМУ это было отклонено? Эти классы действительно являются действительными примерами длительного опроса. - person Prisoner ZERO; 28.09.2011
comment
Настоящий длинный опрос - это не (просто) практика увеличения интервала, когда вы проводите обычный опрос (на ресурсе). Это часть более крупного паттерна ... который в некоторой степени подлежит интерпретации ... но только в определенных областях общей реализации. Тем не менее ... эти классы следуют указанному шаблону! Так что, если у вас есть причина проголосовать против этого ... Мне действительно была бы интересна причина. - person Prisoner ZERO; 12.06.2012
comment
Возможно, он был отклонен, поскольку он напрямую не решает вопрос о простом примере кода. Конечно, я не голосовал против, поэтому могу только догадываться. - person Andrew; 15.06.2012


Вот простой пример длинного опроса в PHP от Эрика Даббельбора используя заголовок Content-type: multipart/x-mixed-replace:

<?

header('Content-type: multipart/x-mixed-replace; boundary=endofsection');

// Keep in mind that the empty line is important to separate the headers
// from the content.
echo 'Content-type: text/plain

After 5 seconds this will go away and a cat will appear...
--endofsection
';
flush(); // Don't forget to flush the content to the browser.


sleep(5);


echo 'Content-type: image/jpg

';

$stream = fopen('cat.jpg', 'rb');
fpassthru($stream);
fclose($stream);

echo '
--endofsection
';

А вот и демонстрация:

http://dubbelboer.com/multipart.php

person Jasdeep Khalsa    schedule 08.12.2012

Я использовал this, чтобы разобраться с Comet, я также настроил Comet с помощью Java Сервер Glassfish и нашел множество других примеров, подписавшись на cometdaily.com

person adam    schedule 02.12.2008

Взгляните на это сообщение в блоге, в котором есть код для простого чат-приложения на Python / Django / gevent.

person Denis Bilenko    schedule 19.11.2009

Ниже приведено решение для длинных опросов, которое я разработал для Inform8 Web. В основном вы переопределяете класс и реализуете метод loadData. Когда loadData возвращает значение или время ожидания операции истекает, он распечатывает результат и возвращается.

Если обработка вашего скрипта может занять больше 30 секунд, вам может потребоваться изменить вызов set_time_limit () на что-то более длительное.

Лицензия Apache 2.0. Последняя версия на github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php

Райан

abstract class LongPoller {

  protected $sleepTime = 5;
  protected $timeoutTime = 30;

  function __construct() {
  }


  function setTimeout($timeout) {
    $this->timeoutTime = $timeout;
  }

  function setSleep($sleep) {
    $this->sleepTime = $sleepTime;
  }


  public function run() {
    $data = NULL;
    $timeout = 0;

    set_time_limit($this->timeoutTime + $this->sleepTime + 15);

    //Query database for data
    while($data == NULL && $timeout < $this->timeoutTime) {
      $data = $this->loadData();
      if($data == NULL){

        //No new orders, flush to notify php still alive
        flush();

        //Wait for new Messages
        sleep($this->sleepTime);
        $timeout += $this->sleepTime;
      }else{
        echo $data;
        flush();
      }
    }

  }


  protected abstract function loadData();

}
person Ryan Henderson    schedule 21.04.2011

Спасибо за код, dbr. Небольшая опечатка в long_poller.htm вокруг строки

1000 /* ..after 1 seconds */

Я думаю так должно быть

"1000"); /* ..after 1 seconds */

чтобы он работал.

Для заинтересованных я попробовал эквивалент Django. Запустите новый проект Django, скажем lp для длительного опроса:

django-admin.py startproject lp

Вызовите приложение msgsrv для сервера сообщений:

python manage.py startapp msgsrv

Добавьте следующие строки в settings.py, чтобы получить каталог templates:

import os.path
PROJECT_DIR = os.path.dirname(__file__)
TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, 'templates'),
)

Определите свои шаблоны URL в urls.py как таковые:

from django.views.generic.simple import direct_to_template
from lp.msgsrv.views import retmsg

urlpatterns = patterns('',
    (r'^msgsrv\.php$', retmsg),
    (r'^long_poller\.htm$', direct_to_template, {'template': 'long_poller.htm'}),
)

И msgsrv / views.py должен выглядеть так:

from random import randint
from time import sleep
from django.http import HttpResponse, HttpResponseNotFound

def retmsg(request):
    if randint(1,3) == 1:
        return HttpResponseNotFound('<h1>Page not found</h1>')
    else:
        sleep(randint(2,10))
        return HttpResponse('Hi! Have a random number: %s' % str(randint(1,10)))

Наконец, шаблоны / long_poller.htm должны быть такими же, как указано выше, с исправленной опечаткой. Надеюсь это поможет.

person xoblau    schedule 15.09.2009
comment
Собственно, "15000" - это синтаксическая ошибка. setTimeout принимает целое число в качестве второго параметра. - person Andrew Hedges; 22.06.2010
comment
Этот ответ требует доработки. Это кульминация одного или нескольких комментариев и отдельного ответа или ответов. - person Brian Webster; 20.09.2012

Это один из сценариев, для которого PHP - очень плохой выбор. Как упоминалось ранее, вы можете очень быстро связать всех своих рабочих Apache, сделав что-то подобное. PHP создан для запуска, выполнения и остановки. Он не предназначен для запуска, подождите ... выполните, остановитесь. Вы очень быстро перегрузите свой сервер и обнаружите, что у вас невероятные проблемы с масштабированием.

Тем не менее, вы все равно можете сделать это с помощью PHP и не убивать ваш сервер с помощью nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule

Вы устанавливаете nginx перед Apache (или чем-то еще), и он позаботится о том, чтобы одновременные соединения оставались открытыми. Вы просто отвечаете полезной нагрузкой, отправляя данные на внутренний адрес, что можно было бы сделать с помощью фонового задания или просто отправлять сообщения людям, которые ждут, когда приходят новые запросы. Это не позволяет процессам PHP оставаться открытыми во время длительного опроса.

Это не эксклюзивно для PHP и может быть выполнено с помощью nginx с любым серверным языком. Нагрузка одновременных открытых подключений равна Node.js, поэтому самая большая привилегия заключается в том, что она избавляет вас от НУЖНОСТИ Node для чего-то вроде этого.

Вы видите, как много других людей упоминают другие языковые библиотеки для проведения длительного опроса, и это не без оснований. PHP, естественно, просто не подходит для такого поведения.

person brightball    schedule 09.04.2014
comment
Это проблема Apache или PHP? Были бы у меня проблемы с долгим опросом, если бы мой PHP-код работал непосредственно на nginx или lighttpd? - person David; 16.07.2015
comment
Это не столько проблема PHP, сколько неправильное использование PHP. При каждом запросе PHP запускает сценарий с нуля, загружая библиотеки по мере необходимости, выполняя его код, а затем завершая работу, пока выполняется сборка мусора, все началось в запросе. За прошедшие годы в PHP было внесено множество модификаций, чтобы минимизировать влияние, такое как поздние статические привязки, отложенная загрузка, кеширование байт-кода в памяти для удаления дискового ввода-вывода и т. Д. Проблема остается в том, что PHP предназначен для запуска и остановки так же быстро. насколько возможно. Языки, которые загружаются один раз / boot и открывают поток для запроса, гораздо лучше подходят для длительного опроса. - person brightball; 27.07.2015
comment
Но чтобы ответить на вопрос, да, вы столкнетесь с проблемой независимо от того, используете ли вы Apache или что-то еще. Так работает PHP. Я должен исправить это, чтобы сказать, что если вы собираетесь иметь известную максимальную нагрузку трафика, PHP будет в порядке. Я видел встроенные системы, использующие PHP, у которых нет проблем, потому что есть всего несколько соединений. Потенциально во внутренней сети компании это также может быть разрешено. Однако для общедоступных приложений вы полностью убьете свои серверы по мере роста трафика. - person brightball; 27.07.2015

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

person shasi kanth    schedule 16.01.2014
comment
Я думаю, что как только веб-сокеты будут реализованы повсюду (вероятно, не на долгие годы), они станут стандартом для такого рода приложений. К сожалению, пока мы не можем полагаться на них в производственных приложениях. - person Richard; 13.04.2014
comment
@Richard Однако вы можете использовать что-то вроде Socket.IO, которое обеспечивает автоматические резервные транспорты, обеспечивая функциональность, подобную веб-сокету, вплоть до IE 6. - person Brad; 03.06.2014

Группа WS-I опубликовала нечто под названием «Надежный безопасный профиль», в котором есть Glass Fish и реализация .NET, которая очевидно хорошо взаимодействуют.

Если повезет, есть Javascript Реализация там тоже.

Существует также реализация Silverlight, в которой используется HTTP Duplex. . Вы можете подключить javascript к Silverlight для получения обратных вызовов при возникновении push.

Также есть платные коммерческие версии.

person halfbit    schedule 20.04.2011

Для реализации ASP.NET MVC см. SignalR, который доступен в NuGet. Обратите внимание, что NuGet является часто устаревшие из источника Git, который очень часто фиксируется.

Узнайте больше о SignalR в блоге Скотта Хансельмана

person halfbit    schedule 09.02.2012

Вы можете попробовать icomet (https://github.com/ideawu/icomet), сервер комет C1000K C ++ построен с помощью libevent. icomet также предоставляет библиотеку JavaScript, ее легко использовать так же просто, как

var comet = new iComet({
    sign_url: 'http://' + app_host + '/sign?obj=' + obj,
    sub_url: 'http://' + icomet_host + '/sub',
    callback: function(msg){
        // on server push
        alert(msg.content);
    }
});

icomet поддерживает широкий спектр браузеров и ОС, включая Safari (iOS, Mac), IE (Windows), Firefox, Chrome и т. д.

person ideawu    schedule 01.10.2013

Простейший NodeJS

const http = require('http');

const server = http.createServer((req, res) => {
  SomeVeryLongAction(res);
});

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

server.listen(8000);

// the long running task - simplified to setTimeout here
// but can be async, wait from websocket service - whatever really
function SomeVeryLongAction(response) {
  setTimeout(response.end, 10000);
}

Например, в Express вы получите response в промежуточном программном обеспечении. Делаете ли вы, что вам нужно, можете выделить все методы с длинным опросом в Map или что-то в этом роде (что видно другим потокам) и вызывать <Response> response.end(), когда будете готовы. В длинных опрашиваемых соединениях нет ничего особенного. Отдых - это то, как вы обычно структурируете свое приложение.

Если вы не понимаете, что я имею в виду, говоря об ограничении, это должно дать вам представление

const http = require('http');
var responsesArray = [];

const server = http.createServer((req, res) => {
  // not dealing with connection
  // put it on stack (array in this case)
  responsesArray.push(res);
  // end this is where normal api flow ends
});

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

// and eventually when we are ready to resolve
// that if is there just to ensure you actually 
// called endpoint before the timeout kicks in
function SomeVeryLongAction() {
  if ( responsesArray.length ) {
    let localResponse = responsesArray.shift();
    localResponse.end();
  }
}

// simulate some action out of endpoint flow
setTimeout(SomeVeryLongAction, 10000);
server.listen(8000);

Как видите, вы действительно можете реагировать на все связи, одно - делать все, что хотите. Для каждого запроса существует id, поэтому вы должны иметь возможность использовать карту и получать доступ к конкретным вызовам из API.

person sp3c1    schedule 24.04.2018