Pertanyaan Bagaimana cara menerapkan “Pemungutan Panjang” dasar?


Saya dapat menemukan banyak informasi tentang cara kerja Long Polling (Misalnya, ini, dan ini), tapi tidak sederhana contoh bagaimana menerapkan ini dalam kode.

Yang bisa saya temukan adalah cometd, yang bergantung pada kerangka JS Dojo, dan sistem server yang cukup kompleks ..

Pada dasarnya, bagaimana saya akan menggunakan Apache untuk melayani permintaan, dan bagaimana saya akan menulis skrip sederhana (misalnya, dalam PHP) yang akan "lama-jajak pendapat" server untuk pesan baru?

Contohnya tidak harus mudah diukur, aman atau lengkap, hanya perlu bekerja!


744
2017-12-02 11:14


asal


Jawaban:


Ini lebih sederhana dari yang saya kira awalnya. Pada dasarnya Anda memiliki halaman yang tidak melakukan apa-apa, sampai data yang ingin Anda kirim tersedia (misalnya, pesan baru tiba).

Berikut ini contoh yang sangat mendasar, yang mengirim string sederhana setelah 2-10 detik. 1 dalam 3 kemungkinan mengembalikan kesalahan 404 (untuk menunjukkan penanganan kesalahan dalam contoh Javascript yang akan datang)

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

Catatan: Dengan situs sungguhan, menjalankan ini pada server web biasa seperti Apache akan dengan cepat mengikat semua "utas pekerja" dan membiarkannya tidak dapat menanggapi permintaan lain. Ada cara di sekitar ini, tetapi disarankan untuk menulis "server polling panjang" dalam sesuatu seperti Python memutar, yang tidak bergantung pada satu utas per permintaan. cometD adalah yang populer (yang tersedia dalam beberapa bahasa), dan Angin topan adalah kerangka kerja baru yang dibuat khusus untuk tugas-tugas seperti itu (itu dibangun untuk kode polling lama FriendFeed) ... tetapi sebagai contoh sederhana, Apache lebih dari cukup! Skrip ini dapat dengan mudah ditulis dalam bahasa apa pun (saya memilih Apache / PHP karena sangat umum, dan kebetulan saya menjalankannya secara lokal)

Kemudian, dalam Javascript, Anda meminta file di atas (msg_srv.php), dan menunggu jawaban. Saat Anda mendapatkannya, Anda bertindak berdasarkan data. Kemudian Anda meminta file dan menunggu lagi, bertindak berdasarkan data (dan ulangi)

Apa yang berikut adalah contoh dari halaman seperti itu .. Ketika halaman dimuat, ia mengirimkan permintaan awal untuk msgsrv.php file .. Jika berhasil, kami menambahkan pesan ke #messages div, kemudian setelah 1 detik kita memanggil fungsi waitForMsg lagi, yang memicu menunggu.

1 detik setTimeout() adalah pembatas laju yang sangat dasar, ia berfungsi dengan baik tanpa ini, tetapi jika msgsrv.php  selalu kembali secara instan (dengan kesalahan sintaks, misalnya) - Anda membanjiri browser dan dapat dengan cepat membeku. Ini akan lebih baik dilakukan memeriksa apakah file berisi respons JSON yang valid, dan / atau menjaga jumlah total permintaan per-menit / detik, dan berhenti dengan tepat.

Jika kesalahan halaman, itu menambahkan kesalahan ke #messages div, menunggu 15 detik dan kemudian mencoba lagi (identik dengan bagaimana kita menunggu 1 detik setelah setiap pesan)

Hal yang baik tentang pendekatan ini adalah sangat tangguh. Jika koneksi internet klien mati, itu akan habis waktu, lalu coba dan sambungkan kembali - ini melekat dalam berapa lama polling bekerja, tidak diperlukan penanganan kesalahan yang rumit.

Bagaimanapun, itu long_poller.htm kode, menggunakan framework 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>

491
2017-12-02 13:15



Saya punya contoh obrolan yang sangat sederhana sebagai bagian dari lumpur cair.

Edit: (karena semua orang menempelkan kode mereka di sini)

Ini adalah obrolan multi-pengguna berbasis JSON lengkap menggunakan jajak pendapat panjang dan lumpur cair. Ini adalah sebuah demo tentang cara melakukan panggilan, jadi abaikan masalah XSS. Tidak ada yang harus menyebarkan ini tanpa membersihkannya terlebih dahulu.

Perhatikan bahwa klien selalu memiliki koneksi ke server, dan segera setelah seseorang mengirim pesan, semua orang akan melihatnya secara langsung.

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

41
2017-12-03 21:08



Angin topan dirancang untuk polling panjang, dan termasuk sangat minim (beberapa ratus baris Python) aplikasi obrolan di /contoh / chatdemo , termasuk kode server dan kode klien JS. Ia bekerja seperti ini:

  • Klien menggunakan JS untuk meminta pembaruan sejak (jumlah pesan terakhir), server URLHandler menerima ini dan menambahkan panggilan balik untuk menanggapi klien ke antrian.

  • Ketika server mendapat pesan baru, peristiwa onmessage akan menyala, memutar melalui callback, dan mengirim pesan.

  • JS sisi-klien menerima pesan, menambahkannya ke halaman, lalu meminta pembaruan sejak ID pesan baru ini.


31
2018-03-04 14:53



Saya pikir klien terlihat seperti permintaan AJAX asynchronous normal, tetapi Anda berharap untuk mengambil "waktu yang lama" untuk kembali.

Server kemudian terlihat seperti ini.

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

outputNewData();

Jadi, permintaan AJAX masuk ke server, mungkin termasuk stempel waktu saat pembaruan terakhir sehingga Anda hasNewData() tahu data apa yang sudah Anda dapatkan. Server kemudian duduk dalam satu lingkaran tidur sampai data baru tersedia. Sementara itu, permintaan AJAX Anda masih terhubung, hanya tergantung di sana menunggu data. Akhirnya, ketika data baru tersedia, server memberikannya ke permintaan AJAX Anda dan menutup koneksi.


24
2017-12-02 11:39



Sini beberapa kelas yang saya gunakan untuk polling panjang di C #. Pada dasarnya ada 6 kelas (lihat di bawah).

  1. Kontroler: Memproses tindakan yang diperlukan untuk membuat respons yang valid (operasi db, dll.)
  2. Prosesor: Mengelola komunikasi asinkron dengan halaman web (sendiri)
  3. IAsynchProcessor: Contoh proses layanan yang mengimplementasikan antarmuka ini
  4. Sevice: Proses meminta objek yang menerapkan IAsynchProcessor
  5. Permintaan: Pembungkus IAsynchProcessor berisi respons Anda (objek)
  6. Tanggapan: Berisi objek atau bidang khusus

17
2017-09-01 14:20



Ini adalah screencast 5 menit yang bagus tentang cara melakukan polling panjang menggunakan PHP & jQuery: http://screenr.com/SNH

Kode sangat mirip dengan dbrContoh di atas.


16
2017-10-20 15:41



Disini adalah contoh polling panjang sederhana dalam PHP oleh Erik Dubbelboer menggunakan Content-type: multipart/x-mixed-replace tajuk:

<?

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

Dan di sini adalah demo:

http://dubbelboer.com/multipart.php


12
2017-12-08 12:23



Saya menggunakan ini untuk mengatasi Comet, saya juga mengatur Comet menggunakan server Java Glassfish dan menemukan banyak contoh lain dengan berlangganan cometdaily.com


11
2017-12-02 11:21