Làm thế nào để tôi thực hiện cơ bản bỏ phiếu dài?


776

Tôi có thể tìm thấy nhiều thông tin về cách Long Polling hoạt động (Ví dụ: cái nàycái này ), nhưng không có ví dụ đơn giản nào về cách thực hiện điều này trong mã.

Tất cả những gì tôi có thể tìm thấy là cometd , dựa trên khung Dojo JS và một hệ thống máy chủ khá phức tạp ..

Về cơ bản, tôi sẽ sử dụng Apache để phục vụ các yêu cầu như thế nào và làm thế nào để tôi viết một tập lệnh đơn giản (giả sử bằng PHP) để "thăm dò lâu" máy chủ cho các tin nhắn mới?

Ví dụ không cần phải mở rộng, bảo mật hoặc hoàn thành, nó chỉ cần hoạt động!

Câu trả lời:


512

Nó đơn giản hơn tôi nghĩ ban đầu .. Về cơ bản, bạn có một trang không có gì, cho đến khi dữ liệu bạn muốn gửi có sẵn (giả sử, có tin nhắn mới đến).

Đây là một ví dụ thực sự cơ bản, nó sẽ gửi một chuỗi đơn giản sau 2-10 giây. 1 trong 3 cơ hội trả lại lỗi 404 (để hiển thị xử lý lỗi trong ví dụ Javascript sắp tới)

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));
?>

Lưu ý: Với một trang web thực, việc chạy này trên một máy chủ web thông thường như Apache sẽ nhanh chóng kết nối tất cả các "luồng công nhân" và khiến nó không thể đáp ứng các yêu cầu khác .. Có nhiều cách để khắc phục điều này, nhưng nên viết một "máy chủ thăm dò ý kiến ​​dài" trong một cái gì đó giống như xoắn của Python , vốn không dựa trên một luồng cho mỗi yêu cầu. cometD là một ngôn ngữ phổ biến (có sẵn bằng nhiều ngôn ngữ) và Tornado là một khung công tác mới được tạo riêng cho các nhiệm vụ đó (nó được xây dựng cho mã bỏ phiếu dài của FriendFeed) ... nhưng như một ví dụ đơn giản, Apache là quá đủ ! Kịch bản này có thể dễ dàng được viết bằng bất kỳ ngôn ngữ nào (Tôi đã chọn Apache / PHP vì chúng rất phổ biến và tôi tình cờ chạy chúng cục bộ)

Sau đó, trong Javascript, bạn yêu cầu tệp trên ( msg_srv.php) và chờ phản hồi. Khi bạn nhận được một, bạn hành động dựa trên dữ liệu. Sau đó, bạn yêu cầu tệp và đợi một lần nữa, hành động theo dữ liệu (và lặp lại)

Dưới đây là ví dụ về một trang như vậy .. Khi trang được tải, nó sẽ gửi yêu cầu ban đầu cho msgsrv.phptệp .. Nếu thành công, chúng tôi sẽ thêm thông báo vào #messagesdiv, sau 1 giây chúng tôi gọi lại hàm WaitForMsg, mà kích hoạt sự chờ đợi.

1 giây setTimeout()là một bộ giới hạn tốc độ thực sự cơ bản, nó hoạt động tốt mà không cần điều này, nhưng nếu msgsrv.php luôn trả về ngay lập tức (ví dụ như có lỗi cú pháp) - bạn làm ngập trình duyệt và nó có thể nhanh chóng đóng băng. Điều này tốt hơn nên được kiểm tra nếu tệp chứa phản hồi JSON hợp lệ và / hoặc giữ tổng số yêu cầu mỗi phút / giây đang chạy và tạm dừng một cách thích hợp.

Nếu trang bị lỗi, nó sẽ thêm lỗi vào #messagesdiv, đợi 15 giây rồi thử lại (giống hệt như cách chúng tôi đợi 1 giây sau mỗi tin nhắn)

Điều tốt đẹp về phương pháp này là nó rất kiên cường. Nếu kết nối internet của máy khách bị chết, nó sẽ hết thời gian, sau đó thử và kết nối lại - đây là thời gian bỏ phiếu hoạt động trong bao lâu, không cần xử lý lỗi phức tạp

Dù sao, long_poller.htmmã, sử dụng khung 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>

7
Không thể một số tin nhắn trượt qua sử dụng ý tưởng này? Trong khoảng thời gian 1 giây đó, giả sử 1000 tin nhắn trò chuyện đã được gửi, làm thế nào để máy chủ biết gửi 1000 tin nhắn cụ thể cho khách hàng đó?
DevDevDev

15
Có lẽ. Đây là một ví dụ rất đơn giản, để thể hiện khái niệm .. Để làm điều này tốt hơn, bạn cần mã phía máy chủ phức tạp hơn, nơi nó sẽ lưu trữ 1000 tin nhắn cho khách hàng cụ thể đó và gửi chúng trong một đoạn. Bạn cũng có thể giảm thời gian chờ của WaitForMsg một cách an toàn
dbr

21
nodejs là một giải pháp phía máy chủ tuyệt vời khác cho các yêu cầu bỏ phiếu dài, với lợi thế bổ sung (trên Twisted) là bạn cũng có thể viết mã máy chủ bằng Javascript.
Husky

8
Đây chỉ là một kết nối AJAX lặp lại đơn giản đến máy chủ với khoảng thời gian 1 giây. Điều này không có gì để làm với "bỏ phiếu dài". Bỏ phiếu dài nên giữ kết nối còn sống, miễn là thời gian chờ của khách hàng.
Deele

6
câu hỏi là kịch bản PHP thực sự làm gì thay vì sleep(rand(2,10));? để không làm gì, hãy thăm dò cơ sở dữ liệu mỗi 100 milisec? khi nào nó quyết định chết
Luis Siquot

41

Tôi đã có một ví dụ trò chuyện thực sự đơn giản như một phần của slosh .

Chỉnh sửa : (vì mọi người dán mã của họ vào đây)

Đây là trò chuyện đa người dùng dựa trên JSON hoàn chỉnh bằng cách sử dụng bỏ phiếu dài và slosh . Đây là bản demo về cách thực hiện các cuộc gọi, vì vậy vui lòng bỏ qua các sự cố XSS. Không ai nên triển khai điều này mà không vệ sinh nó trước.

Lưu ý rằng máy khách luôn có kết nối đến máy chủ và ngay khi có ai gửi tin nhắn, mọi người sẽ thấy nó ngay lập tức.

<?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 <dustin+html@spy.net> -->
<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>

1
Tôi có thể biết làm thế nào điều này luôn luôn được kết nối? Xin lỗi nếu tôi hỏi điều gì đó ngớ ngẩn, nhưng tôi muốn biết điều đó.
Rocky Singh

4
Nó thực hiện HTTP GET và máy chủ chặn GET cho đến khi có sẵn dữ liệu. Khi dữ liệu đến máy chủ, máy chủ sẽ trả lại dữ liệu cho máy khách, xếp hàng bất cứ thứ gì khác có thể đến và sau đó máy khách sẽ kết nối lại và nhận các tin nhắn bị thiếu nếu có, nếu không, nó sẽ chặn lại.
Dustin

4
Ban đầu có thể không rõ ràng, nhưng điều chịu trách nhiệm cho 'trạng thái luôn được kết nối' là ajaxStop với getNewCommentscuộc gọi lại ở đó, vì vậy nó chỉ kích hoạt nó vào cuối mỗi yêu cầu ajax vô tận
hói đầu

32

Tornado được thiết kế để bỏ phiếu dài và bao gồm một ứng dụng trò chuyện rất tối thiểu (vài trăm dòng Python) trong / example / chatdemo , bao gồm mã máy chủ và mã máy khách JS. Nó hoạt động như thế này:

  • Khách hàng sử dụng JS để yêu cầu cập nhật kể từ (số lượng tin nhắn cuối cùng), URLHandler của máy chủ nhận được những cập nhật này và thêm một cuộc gọi lại để trả lời khách hàng vào hàng đợi.

  • Khi máy chủ nhận được một tin nhắn mới, sự kiện onmessage sẽ kích hoạt, lặp qua các cuộc gọi lại và gửi tin nhắn.

  • JS phía máy khách nhận được thông báo, thêm nó vào trang, sau đó yêu cầu cập nhật vì ID thông báo mới này.


25

Tôi nghĩ rằng máy khách trông giống như một yêu cầu AJAX không đồng bộ thông thường, nhưng bạn hy vọng nó sẽ mất một "thời gian dài" để quay lại.

Các máy chủ sau đó trông như thế này.

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

outputNewData();

Vì vậy, yêu cầu AJAX đến máy chủ, có thể bao gồm cả dấu thời gian khi nó được cập nhật lần cuối để bạn hasNewData()biết dữ liệu nào bạn đã có. Sau đó, máy chủ sẽ nằm trong một vòng lặp ngủ cho đến khi có dữ liệu mới. Trong khi đó, yêu cầu AJAX của bạn vẫn được kết nối, chỉ chờ ở đó để chờ dữ liệu. Cuối cùng, khi có dữ liệu mới, máy chủ sẽ cung cấp nó cho yêu cầu AJAX của bạn và đóng kết nối.


10
Đây là một chờ đợi bận rộn chặn chủ đề hiện tại của bạn. Điều đó không có quy mô nào cả.
Wouter Lievens

10
Không, ngủ không phải là một chờ đợi bận rộn. Và toàn bộ vấn đề "chờ đợi" là chặn chuỗi của bạn trong một thời gian. Có lẽ anh ta có nghĩa là 50 mili giây (ngủ (50000)), chứ không phải 50 micro giây! Nhưng dù sao, với một thiết lập Apache / PHP điển hình, có cách nào khác để làm điều này không?
Matt

Chà, từ nhà tiên tri, bạn không thể tạo chức năng chặn tin nhắn trò chuyện mà không phải chờ đợi.
Tomáš Zato - Phục hồi Monica

Tuyệt vời thực sự! Tôi đã xây dựng một hàm đệ quy trong máy chủ để kiểm tra dữ liệu mới. Nhưng sản phẩm tốt nhất để sử dụng bỏ phiếu dài có hiệu quả là gì? Tôi sử dụng Apache bình thường và máy chủ không phản hồi khi tôi mở hơn 4/5 tab trình duyệt :( Tìm kiếm thứ gì đó sẽ được sử dụng với PHP
hiện đại

17

Dưới đây là một số lớp tôi sử dụng để bỏ phiếu dài trong C #. Về cơ bản có 6 lớp (xem bên dưới).

  1. Trình điều khiển : Xử lý các hành động cần thiết để tạo phản hồi hợp lệ (hoạt động db, v.v.)
  2. Bộ xử lý : Quản lý giao tiếp asynch với trang web (chính nó)
  3. IAsynchProcessor : Dịch vụ xử lý các trường hợp thực hiện giao diện này
  4. Dịch vụ : Quy trình yêu cầu các đối tượng triển khai IAsynchProcessor
  5. Yêu cầu : Trình bao bọc IAsynchProcessor chứa phản hồi (đối tượng) của bạn
  6. Trả lời : Chứa các đối tượng hoặc trường tùy chỉnh

2
Được rồi ... vậy TẠI SAO điều này đã được bỏ phiếu? Các lớp này thực sự là ví dụ hợp lệ của bỏ phiếu dài.
Tù nhân ZERO

Thăm dò dài thực sự không phải (đơn giản) thực hành tăng khoảng thời gian trong đó bạn tiến hành một cuộc thăm dò bình thường (trên một tài nguyên). Nó là một phần của một mô hình lớn hơn ... là chủ đề "hơi" để giải thích ... nhưng chỉ trong một số lĩnh vực nhất định của việc thực hiện tổng thể. Điều đó nói rằng ... các lớp học theo mô hình nói! Vì vậy, nếu bạn có một lý do để bỏ phiếu này ... Tôi thực sự sẽ quan tâm đến lý do.
Tù nhân ZERO

Có lẽ nó đã được bỏ phiếu vì nó không trực tiếp giải quyết câu hỏi về một ví dụ mã đơn giản. Tất nhiên tôi đã không bỏ phiếu xuống nên tôi chỉ có thể đoán.
Andrew

16

Đây là một đoạn ghi hình dài 5 phút tuyệt vời về cách thực hiện bỏ phiếu dài bằng PHP & jQuery: http://screenr.com/SNH

Mã khá giống với ví dụ của dbr ở trên.


3
Tôi nghĩ bạn chỉ nên xem đây là phần giới thiệu về bỏ phiếu dài vì việc triển khai này chắc chắn sẽ giết chết máy chủ của bạn với nhiều người dùng đồng thời.
Alfred

Tôi chỉ đang tìm hiểu về tất cả những điều này ... đáng tin cậy hay không, có phải với một vài người dùng ... nói 10 cuộc trò chuyện trở lại?
ngày nào đó

12

Dưới đây là một ví dụ bỏ phiếu dài đơn giản trong PHP của Erik Dubbelboer bằng Content-type: multipart/x-mixed-replacetiêu đề:

<?

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
';

Và đây là một bản demo:

http://dubbelboer.com/multipart.php


11

Tôi đã sử dụng điều này để hiểu rõ hơn về Comet, tôi cũng đã thiết lập Comet bằng máy chủ Java Glassfish và tìm thấy rất nhiều ví dụ khác bằng cách đăng ký vào cometdaily.com



9

Dưới đây là một giải pháp bỏ phiếu dài mà tôi đã phát triển cho Inform8 Web. Về cơ bản, bạn ghi đè lớp và thực hiện phương thức loadData. Khi loadData trả về một giá trị hoặc hết thời gian hoạt động, nó sẽ in kết quả và trả về.

Nếu quá trình xử lý tập lệnh của bạn có thể mất hơn 30 giây, bạn có thể cần phải thay đổi lệnh gọi set_time_limit () thành một cuộc gọi dài hơn.

Giấy phép Apache 2.0. Phiên bản mới nhất trên github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php

Ryan

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();

}

8

Cảm ơn mã, dbr . Chỉ cần một lỗi đánh máy nhỏ trong long_poller.htm xung quanh dòng

1000 /* ..after 1 seconds */

Tôi nghĩ nó nên như vậy

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

cho nó hoạt động.

Đối với những người quan tâm, tôi đã thử một Django tương đương. Bắt đầu một dự án Django mới, nói lp để bỏ phiếu dài:

django-admin.py startproject lp

Gọi cho ứng dụng Trình nhắn tin cho máy chủ tin nhắn:

python manage.py startapp msgsrv

Thêm các dòng sau vào settings.py để có mộtthư mục mẫu :

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

Xác định các mẫu URL của bạn trong urls.py như sau:

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'}),
)

Và thông điệp / xem sẽ giống như:

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)))

Cuối cùng, các mẫu / long_poller.htm phải giống như trên với sửa lỗi chính tả. Hi vọng điêu nay co ich.


Trên thực tế, "15000"là lỗi cú pháp. setTimeout lấy một số nguyên làm tham số thứ 2 của nó.
Andrew Hedges

Câu trả lời này cần làm việc. Đó là đỉnh cao của một hoặc nhiều bình luận và một câu trả lời hoặc câu trả lời riêng biệt.
Brian Webster

8

Đây là một trong những tình huống mà PHP là một lựa chọn rất tồi. Như đã đề cập trước đây, bạn có thể kết nối tất cả các nhân viên Apache của mình một cách nhanh chóng để làm một cái gì đó như thế này. PHP được xây dựng để bắt đầu, thực thi, dừng lại. Nó không được xây dựng để bắt đầu, chờ ... thực thi, dừng lại. Bạn sẽ phá hỏng máy chủ của bạn rất nhanh và thấy rằng bạn có vấn đề mở rộng đáng kinh ngạc.

Điều đó nói rằng, bạn vẫn có thể làm điều này với PHP và để nó không giết chết máy chủ của bạn bằng cách sử dụng nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule

Bạn thiết lập nginx trước Apache (hoặc bất cứ thứ gì khác) và nó sẽ đảm nhiệm việc giữ các kết nối đồng thời mở. Bạn chỉ cần phản hồi với tải trọng bằng cách gửi dữ liệu đến một địa chỉ nội bộ mà bạn có thể thực hiện với một công việc nền hoặc chỉ cần gửi các tin nhắn đến những người đang chờ đợi bất cứ khi nào có yêu cầu mới đến.

Điều này không dành riêng cho PHP và có thể được thực hiện bằng nginx với bất kỳ ngôn ngữ phụ trợ nào. Tải kết nối mở đồng thời bằng Node.js, vì vậy, lợi ích lớn nhất là nó giúp bạn thoát khỏi NEEDING Node cho một cái gì đó như thế này.

Bạn thấy rất nhiều người khác đề cập đến các thư viện ngôn ngữ khác để hoàn thành việc bỏ phiếu dài và đó là lý do chính đáng. PHP chỉ được xây dựng không tốt cho loại hành vi này một cách tự nhiên.


Đây là một vấn đề Apache hay một vấn đề PHP? Tôi có gặp vấn đề với việc bỏ phiếu dài nếu mã PHP của tôi chạy trực tiếp trên nginx hoặc lighttpd không?
David

Đó là một vấn đề PHP ít hơn và lạm dụng PHP nhiều hơn. Trên mỗi yêu cầu, PHP chạy tập lệnh từ đầu, tải các thư viện khi cần, thực thi mã của nó và sau đó tắt trong khi thu thập rác mọi thứ bắt đầu trong yêu cầu. Rất nhiều sửa đổi đã được thực hiện cho PHP trong những năm qua để giảm thiểu tác động như các ràng buộc tĩnh muộn, tải chậm, trong bộ nhớ cache của bộ nhớ cache để loại bỏ I / O đĩa, v.v. Vấn đề vẫn là PHP dự định bắt đầu và dừng nhanh chóng càng tốt Các ngôn ngữ sẽ tải một lần / khởi động và mở một chuỗi cho yêu cầu phù hợp hơn nhiều cho việc bỏ phiếu dài.
bóng sáng

Nhưng để trả lời câu hỏi, vâng, bạn sẽ gặp vấn đề bất kể bạn đang sử dụng Apache hay cái gì khác. Đó chỉ là cách PHP hoạt động. Tôi nên sửa đổi điều này để nói rằng, nếu bạn sắp có một lưu lượng tải tối đa đã biết thì PHP sẽ ổn. Tôi đã thấy các hệ thống nhúng sử dụng PHP không có vấn đề gì vì chỉ có một vài kết nối. Có khả năng trên mạng nội bộ của công ty, điều này cũng có thể được thông qua. Tuy nhiên, đối với các ứng dụng công khai, bạn sẽ hoàn toàn giết chết máy chủ của mình khi lưu lượng truy cập tăng lên.
bóng sáng

4

Tại sao không xem xét các ổ cắm web thay vì bỏ phiếu dài? Họ rất hiệu quả và dễ dàng để thiết lập. Tuy nhiên, chúng chỉ được hỗ trợ trong các trình duyệt hiện đại. Dưới đây là một tài liệu tham khảo nhanh .


Tôi nghĩ rằng một khi websockets được triển khai ở mọi nơi (có thể không phải trong nhiều năm tới) thì chúng sẽ là tiêu chuẩn cho loại ứng dụng này. Thật không may cho bây giờ, chúng tôi không thể dựa vào chúng cho các ứng dụng sản xuất.
Richard

3
@Richard Tuy nhiên, bạn có thể sử dụng một cái gì đó như Socket.IO cung cấp vận chuyển dự phòng tự động, cung cấp chức năng giống như ổ cắm web cho đến IE 6.
Brad

3

Nhóm WS-I đã xuất bản một cái gì đó gọi là "Hồ sơ bảo mật đáng tin cậy"triển khai Glass Fish và .NET có vẻ như hoạt động lẫn nhau tốt.

Với bất kỳ may mắn nào cũng có một Javascript triển khai .

Ngoài ra còn có một triển khai Silverlight sử dụng HTTP Duplex. Bạn có thể kết nối javascript với Silverlight đối tượng để nhận cuộc gọi lại khi xảy ra việc đẩy.

Ngoài ra còn có phiên bản trả tiền thương mại là tốt.



2

Bạn có thể dùng thử icomet ( https://github.com/ideawu/icomet ), một máy chủ sao chổi C1000K C ++ được xây dựng với libevent. icomet cũng cung cấp một thư viện JavaScript, nó rất dễ sử dụng đơn giản như

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 hỗ trợ nhiều Trình duyệt và HĐH, bao gồm Safari (iOS, Mac), IE (Windows), Firefox, Chrome, v.v.


0

NodeJS đơn giản nhất

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);
}

Sản xuất kịch bản khôn ngoan trong Express cho exmaple bạn sẽ nhận được responsetrong phần mềm trung gian. Bạn có cần phải làm gì không, có thể tìm ra tất cả các phương thức được thăm dò dài cho Bản đồ hoặc một cái gì đó (có thể nhìn thấy các luồng khác) và gọi<Response> response.end() bất cứ khi nào bạn sẵn sàng. Không có gì đặc biệt về các kết nối bỏ phiếu dài. Phần còn lại chỉ là cách bạn thường cấu trúc ứng dụng của mình.

Nếu bạn không biết ý của tôi là gì khi tìm hiểu, điều này sẽ cho bạn ý tưởng

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);

Như bạn thấy, bạn thực sự có thể đáp ứng tất cả các kết nối, một, làm bất cứ điều gì bạn muốn. Có idcho mọi yêu cầu để bạn có thể sử dụng bản đồ và truy cập cụ thể trong cuộc gọi api.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.