Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > PHP
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.03.2015, 20:54   #1
s88s
Форумчанин
 
Регистрация: 02.01.2014
Сообщений: 369
По умолчанию моментальный вывод сообщений .

Доброго времени суток !

решил написать свой простенький чат так сказать потренироваться конечно же пишу на php и тут появился вопрос вот какого плана как сделать что бы сообщения появлялись сразу после отправки у всех кто находится в чате ... и нашел вот какое решение Long polling и после того как я все смог прикрутить к своему чату появился один маленький но серьезный вопрос а не будет ли грузить сервер этот чудо ...

Выкладываю оригиналы того что я нашел ...
ajax.php
PHP код:
<?php

// если нет функции ftok, то напишем её сами
if( !function_exists('ftok') )
{
    
// взята с php.net
    
function ftok($pathname$proj_id) {
       
$st stat($pathname);
       if (!
$st) {
           return -
1;
       }
      
       
$key sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id 0xff) << 24)));
       return 
$key;
    }
}

// возьмём для хранения, код с примера чата с ajax
// и доработаем его
try {
    
// конект к СУБД
    
$dbh = new PDO("mysql:dbname=test;host=localhost""root""", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));

    
// получаем id последнего сообщения
    
$last_id = isset($_REQUEST['last_id']) ? (int)$_REQUEST['last_id'] : 0;
    
// текст
    
$text = isset($_POST['text']) ? trim($_POST['text']) : '';
    
    
// преобразуем имя файла в идентификатор блока памяти
    
$key ftok(__FILE__'t');
    
// получаем доступ к памяти
    // мы будем хранить максимальный ID, а значит, нам хватит 4 байта памяти
    
$memory shmop_open($key'c'06004);
    
    if (!empty(
$text)) {
        
// вставка новой записи
        
$sth $dbh->prepare("INSERT INTO `chat` (`text`) VALUES (:text)");
        
$sth->execute(array(':text' => $text));
        
        
// последний сгенерированный ID
        
$id $dbh->lastInsertId();
        
// пишем его в разделяемую память
        // используем pack, так как данные нужно передать как строку
        
shmop_write($memorypack('I'$id), 0);
    }
    
    
// результирующий массив
    
$result = array();
    
    
//достаём id из памяти
    
$data unpack('I'shmop_read($memory04));
    
// если id = 0, возможно сервер перезапускали
    
if (!$data[1]) {
        
// получим последний id
        
$sth $dbh->query("SELECT MAX(`id`) FROM `chat`");
        
$max = (int)$sth->fetchColumn();
        if (
$max) {
            
// запишем максимальный ID в память
            
shmop_write($memorypack('I'$max), 0);
            
$data[1] = $max;
        }
    }
    
// если ид в памяти меньше того что мы знаем
    
while ($data[1] <= $last_id) {
        
// зацикливаем в ожидании ид который мы не знаем, но что бы не грузить процессор ставим sleep в 1 секунду
        
sleep(1);
        
$data unpack('I'shmop_read($memory04));
    }
    
    
// загружаем сообщения, которые были после последнего полученного нами, но не более 20
    
$sth $dbh->prepare("SELECT * FROM `chat` WHERE `id` > :last_id ORDER BY `id` DESC LIMIT 20");
    
$sth->bindParam(':last_id'$last_idPDO::PARAM_INT);
    
$sth->execute();
    
$result array_reverse($sth->fetchall());
    
    
// отдаём массив сообщений в формате JSON
    
echo json_encode($result);
} catch (
PDOException $e) {
    echo 
'Ошибка подключения: ' $e->getMessage();
}
"Я не волшебник, я только учусь"
s88s вне форума Ответить с цитированием
Старый 27.03.2015, 20:56   #2
s88s
Форумчанин
 
Регистрация: 02.01.2014
Сообщений: 369
По умолчанию

Все не поместилось за один раз вот второй файл
index.html
Код HTML:
<script src="jquery.min.js"></script>

<script>

/*
    Для статьи http://codediscuss.ru/blogs/14-ajax-chat-na-php-i-mysql
*/

$(function(){
    var chat = $('#chat')[0]; // Окно чата
    var form = $('#chat-form')[0]; // форма
    var xhr; // запрос
    
    // вешаем обработчик на отправку формы
    $('#chat-form').submit(function(event){
        
        // поле ввода
        var text = $(form).find('input[type="text"]');

        // выключаем форму пока не пришел ответ
        $(form).find('input').attr("disabled", true);
        
        // отправка сообщения
        update(text);
        
        // что бы форма не перезагружала страницу
        return false;
    });
    
    function update(text) {
        // что шлём
        var send_data = { last_id: $(chat).attr('data-last-id') };
        if (text)
            send_data.text = $(text).val();
        
        if (xhr) {
            xhr.abort();
        }
        // шлём запрос
        xhr = $.post(
            'ajax.php',
            send_data, // отдаём скрипту данные
            function (data) {
                // ссылка пришла?
                if (data && $.isArray(data)) {
                    $(data).each(function (k) {
                        // формируем наше сообщение
                        var msg = $('<div>' + data[k].created + ': ' + data[k].text + '</div>');
                        // и цепляем его к чату
                        $(chat).append(msg);
                        // если ласт ид меньше пришедшего
                        if (parseInt($(chat).attr('data-last-id')) < data[k].id)
                            // запоминаем новый ласт ид
                            $(chat).attr('data-last-id', data[k].id);
                    });
                    
                    // если это отправка, то при получении ответа, включаем форму
                    if (text) {
                        // вклчюаем форму
                        $(form).find('input').attr("disabled", false);
                        // и очищаем текст
                        $(text).val('');
                    }

                    // прокрутка
                    $(chat).scrollTop(chat.scrollHeight);

                    // зацикливаем вызов обновления
                    update();
                }
            },
            'JSON' // полученные данные рассматривать как JSON объект
        );
    }

    // что бы при загрузке получить данные в чат, вызываем сразу апдейт
    update();
});
</script>

<style>
#chat { overflow-x: scroll; height: 200px; }
</style>
<div id="chat" data-last-id="0"></div>
<form id="chat-form">
    <input type="text" id="chat-msg"/>
    <input type="submit" value="написать"/>
</form>
"Я не волшебник, я только учусь"
s88s вне форума Ответить с цитированием
Старый 27.03.2015, 21:44   #3
Stanislav
Квадрокоптерист
Участник клуба Подтвердите свой е-майл
 
Регистрация: 29.09.2007
Сообщений: 1,824
По умолчанию

Много расписывать не буду.. но скажу в общих чертах

1. почитайте про comet и статейку на хабре вам нашел

Вообще на самом деле вопросы рейл - тайма это не тривиальные вопросы. я глубоко занимался этой темой по необходимости, поэтому если вы всерьез озабочены этой темой вам лучше уйти в сторону nodejs с его прекрасным socket.io либо можно уйти в сторону python с его связкой tornado+socket.io опять так же. я применял эти технологии в продакшене поэтому пишу по опыту. при тестировании простой сервер выдерживал до 300 тыс соединений без последствий, дальше не хватало памяти, был серьезный подход со стороны настройки nginx.

что касается Long poll и т.д считаю не серьезным подходом. да и сам инструмент язык php не располагает решать эту задачу как выше описанные инструменты. знаете под каждую задачу идет свой инструмент. это как раз тот случай

Но вы не расстраивайтесь. если вам все же очень хочется чата сделайте псевдо-рейл тайм. к примеру централизованный скрипт раз в 5 сек выполняет запрос к базе (запрос самый простой select count(id) from msg id индекс) получили число запомнили если в следующий раз число отличается делайте еще один запрос на выборку сообщений и результат записывайте в div вашего чата.

Будут вопросы пишите.
Я часть той силы, что вечно хочет зла, но вечно совершает благо..

Последний раз редактировалось Stanislav; 27.03.2015 в 21:47.
Stanislav вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вывод отладочных сообщений Sam Gold Win Api 6 19.02.2012 16:11
Вывод новых сообщений цикла с верху. Андрейкин PHP 5 28.08.2010 19:23
Вывод сообщений\уведомлений\ошибок на экран Pirotexnik Общие вопросы C/C++ 8 03.06.2010 10:39
вывод сообщений из Unit2 в Unit1 ListBox1 fize Помощь студентам 4 12.12.2009 17:35
Вывод сообщений в Билдере Lanist Общие вопросы C/C++ 1 21.07.2008 10:05