1. ホーム
  2. php

[解決済み] 基本的な「ロングポーリング」の実装方法を教えてください。

2022-03-23 12:53:03

質問

Long Pollingがどのように機能するかについての情報はたくさんあります。 これ および この を含む)、ただし シンプル をコードで実装する例です。

私が見つけることができるのは コメット これは、Dojo JS フレームワークと、かなり複雑なサーバーシステムに依存しています。

基本的に、リクエストを処理するために Apache をどのように使用し、新しいメッセージについてサーバを "long-poll" する簡単なスクリプト(例えば PHP で)をどのように書けばよいのでしょうか?

この例は、拡張性、安全性、完全性は必要ありません。

解決するには?

最初に考えていたより簡単です。基本的には、送信したいデータが利用可能になるまで(例えば、新しいメッセージが到着するまで)、何もしないページがあります。

以下は本当に基本的な例で、2~10秒後に簡単な文字列を送信します。3分の1の確率で404のエラーが返ってきます。

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のような通常のウェブサーバでこれを実行すると、すぐにすべてのquot;ワーカスレッド"を使い果たしてしまい、他のリクエストに応答できなくなります。これを回避する方法はありますが、Pythonのようなものでquot;long-pollサーバーを書くことをお勧めします。 ねじれた これは、1つのリクエストにつき1つのスレッドに依存しないものです。 コメットD はポピュラーなものであり(数ヶ国語で利用可能)、また トルネード はこのようなタスクのために特別に作られた新しいフレームワークです(FriendFeedのロングポーリングコードのために作られました)...しかし、単純な例としては、Apacheは十分すぎるほどです このスクリプトはどんな言語でも簡単に書くことができます(Apache/PHPを選んだのは、これらが非常に一般的であり、たまたまローカルで動作していたからです)

そして、Javascriptで上記のファイルをリクエストします( msg_srv.php を実行し、応答を待ちます。 応答があったら、そのデータに基づいて行動する。次に、ファイルを要求し、再び待ち、データに対応する(そして繰り返す)。

以下は、そのようなページの例である。ページが読み込まれると、最初のリクエストとして msgsrv.php ファイルです。成功した場合、そのメッセージを #messages 1秒後に再度waitForMsg関数を呼び出し、待ちを発生させます。

1秒間の setTimeout() は本当に基本的なレートリミッターで、これなしでも問題なく動作しますが、もし msgsrv.php 常に を即座に返します(例えば構文エラーなど) - ブラウザが殺到して、すぐにフリーズしてしまうこともあります。これは、ファイルが有効な JSON 応答を含んでいるかどうかをチェックしたり、リクエスト数/分/秒を記録して、適切に一時停止したりする方がよいでしょう。

ページがエラーになった場合、そのエラーを #messages 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>