Приложение для чата AJAX Polling

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

Некоторые участники проекта предложили использовать XMPP через BOSH, я сказал, что это все равно что пытаться поймать рыбу с помощью лодочной сети, и предложил более простой метод, такой как простой веб-чат Ajax/MySQL, но мы беспокоимся о производительности. попадание на сервер из-за постоянного опроса множества открытых одновременно чатов.

Кто-нибудь делал что-то подобное раньше? Чтобы вы посоветовали?

Ответы

Ответ 1

Вы также можете посмотреть на комету.

Он используется GTalk, Meebo и многими другими приложениями чата. Несколько лет назад, когда я экспериментировал с ним, было не так много библиотек или деталей о серверной архитектуре для его реализации, но, похоже, сейчас есть намного больше вещей.

Посмотрите на проект Cometd для получения дополнительной технической информации.

Ответ 2

Что бы вы порекомендовали?

XMPP через BOSH

Не нужно изобретать свой собственный формат сообщения и транспортный протокол, если у кого-то еще есть. Если вы попытаетесь, он будет медленно расти настолько же сложно, как BOSH, но без поддержки сторонней библиотеки или стандартизации.

Ответ 3

Если вам не нравится идея HTTP-опроса, у вас может быть Flash-фильм на странице чата с постоянным подключением к некоторому деамону на сервере, тогда Flash-фильм будет вызывать функции JavaScript на клиент для обновления чата при появлении новых сообщений. (Если вам не нужен интерфейс Flash для вашего чата.)

Ответ 4

Вы также можете посмотреть в комету.

Я думал, что все используют комет для такого рода вещей.

BOSH - это стандарт для транспортировки XMPP через HTTP. Он включает комет для передачи данных клиенту.

Ответ 5

Существует очень хороший сервер для обработки нажатия сообщения от сервера к браузеру (дублируется Comet) - Orbited. Он легко интегрируется с другими технологиями (Django, Rails, PHP и т.д.), Так же как memcached.

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

Ответ 6

Я сделал то же самое несколько месяцев назад и повеселился, просто играя с концепциями. Я фактически использовал метод forever-frame вместо опроса.

Ниже приведен код js файла "кометы", который содержит общие понятия, необходимые для настройки "партийного чата".

function Comet(key) {

  var random = key;
  var title = 'Comet';
  var connection = false;
  var iframediv = false;
  var browserIsIE = /*@[email protected]*/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);
  }
}

Ответ 7

Трюк заключается в том, чтобы понять, что единственный раз, когда ваше приложение должно вызывать CGI на сервере, - это когда кто-то что-то говорит. Для регулярных опросов опросите статическую страницу, обновляющую ваш CGI script всякий раз, когда появляется новый чат. Используйте HEAD-запросы, сравнивайте отметки времени с теми, которые были замечены в последний раз, и выполняйте только GET, когда они меняются. У меня есть приложение простого наивного чата, реализованное таким образом, а загрузка и использование полосы пропускания незначительны для нескольких десятков одновременных пользователей, которые у нас есть.

Ответ 8

Я думал, что все используют комет для такого рода вещей.

Ответ 9

Я согласен с Джоном. Но был еще один вопрос, на который не ответил.
Я сделал это, но вместо того, чтобы использовать базу данных, мы использовали плоский файл, но в конечном итоге он испортил сервер, но только когда у нас было ~ 450 активных пользователей, и если бы мы сделали это с базой данных, это, вероятно, лучше.
Это было сделано на основной учетной записи хостинга от Godaddy.

Edit: BTW Godaddy звучал меньше, чем забавлялся, когда я получил телефонный звонок.

Ответ 10

Я думаю, что опрос - это самый простой подход, и он порекомендовал бы это в первую очередь. Если загрузка становится проблемой, она рассматривает более сложные методы. Хорошая дискуссия о плюсах и минусах здесь - http://www.infoq.com/news/2007/07/pushvspull
http://ajaxian.com/archives/a-report-on-push-versus-pull

Ответ 12

Я только что нашел этот пост, он старый, но концепция опроса дает проблемы для большого количества poeple. Поэтому я приведу пример реализации. Но прежде, чем дать это вам, я должен дать вам совет, который заставил меня с ума сойти на какое-то время:

Когда вы проводите опрос, вы должны позаботиться о поведении сеансов (условия гонки). Чтобы сделать его простым: если вы открываете сеанс, файл сеанса блокируется до тех пор, пока сеанс не будет закрыт, чтобы избежать того, чтобы 2 адаса вносили в него разные данные. Итак, если вам нужен сеанс, чтобы проверить, зарегистрирован ли пользователь или нет, всегда закрывайте сеанс перед опросом.

Моя демонстрация дает вам пример реализации опроса в PHP. Я не буду использовать базу данных, но вместо нее. Когда вы нажмете кнопку опроса, вы войдете в цикл и до тех пор, пока файл не будет изменен, вы останетесь в режиме опроса. Когда вы заполните форму и нажмите "Release", то, что вы набрали, будет сохранено в файле. Время изменения файла изменится, поэтому опрос остановится.

Совет. Используйте инструмент, например 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>

Вы можете попробовать здесь