Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Реализация приём/отправка сообщений как Вконтакте


Автор: numerovan 11.10.2013, 18:39
Здравствуйте, предлогаю сделать один пост, где нормально будет описан метод реалиции отправки/получения сообщений в реальном времени с их уведомлением ... в общем как Вконтакте. Сидел вот целый день сегодня , читал разные статьи, пробывал, тестировал ... мало к чему пришёл, последняя надежда наверно на этот форум.
В общем вот что есть:
В HTML-е делаю следующее, через яваскрипт
Код

var ws = new WebSocket('ws://site.ru:80/folder/file.php'); 
        ws.onopen = function() { alert("Открыт"); // вызывается при открытии соединения 
        }; 
        ws.onerror = function(e) { alert("Ошибка"); // вызывается в случае ошибки, например, при обрыве связи 
        }; 
        ws.onclose = function() { alert("Закрыт"); // вызывается при закрытии соединения 
        }; 
        ws.onmessage = function(msg) { alert(msg.data);
            // вызывается, когда сервер посылает сообщение клиенту.
            // сообщение содержится в msg.data. 
        }; 
        // Вот как послать некоторые данные на сервер:
        ws.send('some data'); 
        
        // Как закрыть сокет:
        ws.close();

Далее php файл, так сказать "проходная дверь" через эти запросы, лежит допустим тут www.site.ru:80/folder/file.php
Код

header('Content-Type: text/plain;'); // хэйдер возвращение данных
set_time_limit(0); // заставляет работать php-скрипт как демон 
ob_implicit_flush(true); // отправляет информацию вне зависимости от того, закончил ли работать php-скрипт или нет
$sockets = array(); // все сокеты
$handshakes = array(); // массив рукопожатий (отдаём информацию о том, что это не просто сокет, а сокет по стандарту WebSocket

$sockets["server"] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);  // создаём главный сокет-сервер, к которому будут обращаться клиенты
socket_bind($sockets["server"], "localhost", 80); // прикрепляем главный сокет-сервер к адресу ws://localhost:10001/%server%.php
socket_set_option($sockets["server"],SOL_SOCKET,SO_REUSEADDR,1); // разрешаем использовать один порт для нескольких соединений
socket_listen($sockets["server"], 20); // ставим лимит подключений (20)

while(true){ // скрипт работает постоянно
    $changed_sockets = $sockets; 
    $num_sockets = socket_select($changed_sockets, $write=NULL,$exceptions=NULL,NULL); // проверим все сокеты на изменение статуса по сравнению с прошлым разом
    foreach($changed_sockets as $socket){ // просмотрим каждый из сокетов, который изменил свой статус
      if($socket == $sockets["server"]){ // значит серверу пришли данные о установлении связи между клиентом и сервером
            if (($client = socket_accept($sockets["server"])) >= 0) $sockets[] = $client; // если удалось установить связь, то добавляем в список всех сокетов
      }else{
            $index = array_search($socket, $sockets);
            $len = @socket_recv($socket,$buffer,4096,0); // получаем информацию от сокета
            if($len == 0) { // если статус сокета изменился, а данных нет, то значит сокет закрылся и мы должны убрать его из списка
                  unset($sockets[$index]);
                  unset($handshakes[$index]);
                  socket_close($socket);
            }
            else if(!isset($handshakes[$index])){ // говорили ли мы уже этому подключению, что мы - WebSocket?
                 $buffer = substr($buffer,strpos($buffer,"Sec-WebSocket-Key: ")+19);
                 $accept = base64_encode(sha1(substr($buffer,0,strpos($buffer,"\r\n")) . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
                 $upgrade  = "HTTP/1.1 101 Switching Protocols\r\n" .
                             "Upgrade: websocket\r\n" .
                             "Connection: Upgrade\r\n" .
                             "Sec-WebSocket-Accept: " . $accept . "\r\n\r\n" .
                             "Sec-Websocket-Extensions=x-webkit-deflate-frame"  . chr(0);
                
                 socket_write($socket,$upgrade,strlen($upgrade)); // отправляем пакет о нас
                 $handshakes[$index] = true; // теперь сказали
            }
            else echo 'buf:'.$buffer."\r\n";
      }
    }
}

реализацию данного примера взял из  ... не могу найти сейчас, где-то раздабыл.
Проблема следующая сейчас : при загруке старницы сразу показываеться ОШИБКА через яваскрипт при реализации объекта сокета.

Что вообще делать то дальше ?

Добавлено через 3 минуты и 32 секунды
на сервере стоит php 5.2.17, вроде всё что нужно включено для этого, браузер тоже говорит что может работать с Вебсокетом через яваскрипт. На сервере отдельно тестил работу сокетов, тоже всё нормально работает ...

Автор: Sanchezzz 12.10.2013, 18:52
Ны пыхе это изврат через демона делать, то ли дело когда серверная морда в nodejs под это...

Автор: Platon 19.10.2013, 14:59
Цитата(Sanchezzz @  12.10.2013,  19:52 Найти цитируемый пост)
Ны пыхе это изврат через демона делать, то ли дело когда серверная морда в nodejs под это...


что значит изврат через демона? в чём преимущество нодджс?

Автор: numerovan 21.10.2013, 23:08
Изучаю сейчас node.js когда время есть, думаю эту тему нужно перенести в соответствующую рубрику. Тема не закрыта, буду пытаться докопаться до истины, результаты полюбому сюда выкладу.

Автор: Sanchezzz 22.10.2013, 07:40
Цитата

что значит изврат через демона? в чём преимущество нодджс?

Смотри у тебя пых в стандартной ситуации отработал и ушел, что бы скрипт работал вечно его создают как deimon. (служба)  который сидит и ждет пока на него с неба не упадет что то. 

Нодежс приложение работает как служба причем все это дело из коробки.
Выдерживает бестыжие количество соединений, быстрый почти мгновенный отклик, асинхронность спс ( JS за такую фичу отдельно), что делает его хорошим инструментом для многопользовательским приложениям. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)