14

私が現在取り組んでいるプロジェクトでは、Web チャット アプリケーションを開発する必要があります。これは、非常に複雑なチャットではなく、特定のトピックについて話すために 2 人を接続する方法であり、認証は一切必要ありません。 2 人のユーザーのうちの 1 人については、顔文字やアバターなどをサポートする必要はありません。

一部のプロジェクト メンバーは、BOSH を介して XMPP を使用できることを提案しました。私は、それは船の網で魚を捕まえようとするようなものであり、単純な Ajax/MySQL Web チャットのような、より単純な方法を提案しましたが、パフォーマンスが心配です。同時に開いている多くのチャットの絶え間ないポーリングにより、サーバーでヒットします。

誰かが前にこのようなことをしたことがありますか? あなたは何をお勧めします?

4

12 に答える 12

7

また、 Cometを調べることもできます。

GTalk、Meebo、その他多くのチャット アプリケーションで使用されています。数年前に私が実験していたときは、それを実装するためのライブラリやサーバー アーキテクチャの詳細はあまりありませんでしたが、現在はさらに多くのものが出回っているようです。

詳細な技術情報については、cometdプロジェクトを参照してください。

于 2008-08-30T00:29:37.490 に答える
5

あなたは何をお勧めします?

BOSH経由のXMPP

他の誰かが発明したときに、独自のメッセージ形式とトランスポート プロトコルを発明する必要はありません。試してみると、ゆっくりと BOSH と同じくらい複雑になりますが、サードパーティ ライブラリのサポートや標準化のメリットはありません。

于 2008-08-30T00:22:22.577 に答える
3

HTTP ポーリングのアイデアが気に入らない場合は、チャット ページに Flash ムービーを配置して、サーバー上のデーモンに常時接続することができます。Flash ムービーは、クライアントで JavaScript 関数を呼び出して更新します。新しいメッセージが来るとチャットします。(チャット用の Flash インターフェースが必要でない限り..)

于 2008-09-21T16:09:21.060 に答える
2

また、Comet を調べることもできます。

こういうことにはみんなcometdを使っていると思っていました。

BOSH は、HTTP を介して XMPP を転送するための標準です。これには、データをクライアントにプッシュするための Comet が含まれます。

于 2008-08-30T02:04:27.590 に答える
2

サーバーからブラウザーへのメッセージのプッシュを処理するための非常に優れたサーバーがあります ( Cometと呼ばれます) - Orbited。memcached と同様に、他のテクノロジ (Django、Rails、PHP など) と簡単に統合できます。

深刻な負荷を処理したい場合は、実際にチェックする必要があります。それ以外の場合は、単純な Ajax ポーリングが最善の方法です。

于 2008-09-21T14:34:31.863 に答える
1

私は数か月前にこれとまったく同じことを行い、コンセプトをいじって楽しんでいました. 実際には、ポーリングの代わりに永久フレーム手法を使用しました。

以下のコードは、「パーティー チャット」のセットアップに必要な一般的な概念を含む「comet」js ファイルです。

function Comet(key) {

  var random = key;
  var title = 'Comet';
  var connection = false;
  var iframediv = false;
  var browserIsIE = /*@cc_on!@*/false;
  var blurStatus = false;
  var tmpframe = document.createElement('iframe');
  var nl = '\r\n';

  this.initialize = function() {
    if (browserIsIE) {
      connection = new ActiveXObject("htmlfile");
      connection.open();
      connection.write("<html>");
      connection.write("<script>document.domain = '"+document.domain+"'");
      connection.write("</html>");
      connection.close();
      iframediv = connection.createElement("div");
      connection.appendChild(iframediv);
      connection.parentWindow.comet = comet;
      iframediv.innerHTML = "<iframe id='comet_iframe' src='./comet.aspx?key="+random+"'></iframe>";
    } else {
      connection = document.createElement('iframe');
      connection.setAttribute('id', 'comet_iframe');
      iframediv = document.createElement('iframe');
      iframediv.setAttribute('src', './comet.aspx?key='+random);
      connection.appendChild(iframediv);
      document.body.appendChild(connection);
    }
  }

  // this function is called from the server to keep the connection alive
  this.keepAlive = function () {
    if (!browserIsIE) {
        mozillaHack();
    }
  }

  // this function is called from the server to update the client
  this.updateClient = function (value) {
    var outputDiv = document.getElementById('output');
    outputDiv.value = value + nl + outputDiv.value;
    if (blurStatus == true) {
        document.title = value;
    }
    if (!browserIsIE) {
        mozillaHack();
    }
  }

  this.onUnload = function() {
    if (connection) {
      // this will release the iframe to prevent problems with IE when reloading the page
      connection = false;
    }
  }

  this.toggleBlurStatus = function(bool) {
    blurStatus = bool;
  }

  this.resetTitle = function() {
    document.title = title;
  }

  function mozillaHack() {
    // this hack will fix the hour glass and loading status for Mozilla browsers
    document.body.appendChild(tmpframe);
    document.body.removeChild(tmpframe);
  }
}
于 2008-08-30T02:05:04.670 に答える
1

秘訣は、アプリがサーバー上で CGI を呼び出す必要があるのは、誰かが何かを言ったときだけであることを認識することです。通常のポーリングでは、新しいチャットがあるたびに CGI スクリプトが更新する静的ページをポーリングします。HEAD リクエストを使用し、タイムスタンプを最後に表示されたものと比較し、それらが変更された場合にのみ完全な GET を実行します。この方法で単純な単純なチャット アプリケーションを実装しましたが、負荷と帯域幅の使用量は、数十人の同時ユーザーに対しては無視できます。

于 2008-09-21T14:38:08.050 に答える
0

みんなこのようなことでcometdを使っていると思いました。

于 2008-08-30T01:54:36.943 に答える
0

私はジョンに同意します。しかし、答えられなかった別の質問がありました。
私はこれを行いましたが、データベースを使用する代わりにフラット ファイルを使用したため、最終的にはサーバーが機能しなくなりましたが、アクティブ ユーザーが 450 人に達するまではそうではありませんでした。より良い。
これは、Godaddy の基本的なホスティング アカウントで行われました。

編集:ところで、電話を受けたとき、ゴダディはそれほど面白がっていないように聞こえました。

于 2008-08-30T02:52:11.967 に答える
0

チェックアウトSpeeqe。舞台裏で BOSH と XMPP を使用する Web ベースのチャット ルーム用のオープン ソース ソリューションです。

于 2009-05-06T10:57:51.173 に答える
0

ポーリングは最も簡単なアプローチであり、最初にそれをお勧めします。負荷が問題になる場合は、より複雑な手法を検討してください。長所と短所に関する良い議論はここにあります - http://www.infoq.com/news/2007/07/pushvspull
http://ajaxian.com/archives/a-report-on-push-versus-pull

于 2008-09-21T14:31:09.737 に答える
0

この投稿を見つけたばかりですが、古いですが、ポーリングの概念は多くの人に問題を引き起こします. ということで実装例を載せておきます。しかし、その前に、少し前に私を怒らせたアドバイスをしなければなりません。

ポーリングするときは、セッションの動作 (競合状態)に注意する必要があります。簡単にするために:セッションを開くと、セッションが閉じられるまでセッションファイルがロックされ、2つのスレッドが異なるデータを書き込むのを防ぎます。そのため、ユーザーがログに記録されているかどうかを確認するセッションが必要な場合は、ポーリングの前に常にセッションを閉じてください。

私のデモでは、PHP でのポーリングの実装例を示します。データベースではなくファイルを使用します。ポーリング ボタンをクリックするとループに入り、ファイルが変更されるまでポーリングを続けます。フォームに入力してリリースをクリックすると、入力した内容がファイルに保存されます。ファイルの変更時刻が変更されるため、ポーリングが停止します。

ヒント: Firebugなどのツールを使用して、何が起こっているかを確認してください。

では、私の英語よりも良い言語で話しましょう :

<?php

    // For this demo
    if (file_exists('poll.txt') == false) {
        file_put_contents('poll.txt', '');
    }

    if (isset($_GET['poll'])) {

        // Don't forget to change the default time limit
        set_time_limit(120);

        date_default_timezone_set('Europe/Paris');
        $time = time();

        // We loop until you click on the "release" button...
        $poll = true;
        $number_of_tries = 1;
        while ($poll)
        {
            // Here we simulate a request (last mtime of file could be a creation/update_date field on a base)
            clearstatcache();
            $mtime = filemtime('poll.txt');

            if ($mtime > $time) {
                $result = htmlentities(file_get_contents('poll.txt'));
                $poll = false;
            }

            // Of course, else your polling will kill your resources!
            $number_of_tries++;
            sleep(1);
        }

        // Outputs result
        echo "Number of tries : {$number_of_tries}<br/>{$result}";
        die();
    }

    // Here we catch the release form
    if (isset($_GET['release']))
    {
        $data = '';
        if (isset($_GET['data'])) {
            $data = $_GET['data'];
        }
        file_put_contents('poll.txt', $data);
        die();
    }

?>

<!-- click this button to begin long-polling -->
<input id="poll" type="button" value="Click me to start polling" />

<br/><br/>

Give me some text here :
<br/>
<input id="data" type="text" />
<br/>

<!-- click this button to release long-polling -->
<input id="release" type="button" value="Click me to release polling" disabled="disabled" />

<br/><br/>

Result after releasing polling :
<div id="result"></div>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">

// Script to launch polling
$('#poll').click(function() {
    $('#poll').attr('disabled', 'disabled');
    $('#release').removeAttr('disabled');
    $.ajax({
        url: 'poll.php',
        data: {
            poll: 'yes' // sets our $_GET['poll']
        },
        success: function(data) {
            $('#result').html(data);
            $('#poll').removeAttr('disabled');
            $('#release').attr('disabled', 'disabled');
        }
    });
});

// Script to release polling
$('#release').click(function() {
    $.ajax({
        url: 'poll.php',
        data: {
            release: 'yes', // sets our $_GET['release']
            data: $('#data').val() // sets our $_GET['data']
        }
    });
});

</script>

ここで試すことができます

于 2012-09-14T19:08:29.717 に答える