Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Интернет » Web-программирование » PHP5, AS2 (AS3) Socket

Модерирует : Cheery

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Добрый день. Дошли руки до реализации многопоточности. А голова не дошла.
 
Есть образная задача, в которой два пользователя двигают свои клипы во флеше. Движения должны максимально синхронно отображаться на обоих мониторах.
Сервер должен передавать данные обоим пользователям, например, куда двигать нельзя и наоборот.
 
Существуют ли рабочие "фреймворки" для работы с сокетами? Где можно увидеть живой и настоящий пример рабочей связки FLASH+PHP+FLASH?
 
Начитался уже массу статей, экспериментировал с двумя самопальными классами по работе с сокетами, но мне так и не удалось хотя бы получить эхо от сервера в клиенте.
 
Тестирую на Denver с пакетом расширений, socket сам по себе работает. Соединения создаются, о чем удаётся даже увидеть в логах. При этом в сетевых соединениях я не вижу, чтобы апач слушал указанный порт. Хотя кол-во соединений растет, но порты всё время разные. Апач в результате приходится перезапускать.
 
В принципе, такую задачу можно решать на обычных вариантах ajax, но скорость и количество соединений по http - не оправдывает.
 
А посути, главная цель наверное в том, чтобы запросы и ответы шли только на одно соединение от клиента и их можно было выстраивать в очередь, отсекать дублирующиеся или пускать "совместно".
 
Я пробовал примерно-следующим алгоритмом:
 

Код:
 
Клиент:
 
  $s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
   socket_bind($s, '127.0.0.1', 9876); //порты пробовал разные
   socket_listen($s);
   $inc = socket_accept($s);
   socket_set_nonblock($inc);// для множественных подключений, хотя я не совсем ещё разобрался что к чему
   $timeStart = microtime(true);
   do {
       if (5 < microtime(true)-$timeStart) {
           echo 'TIMEOUT';
           break;
       }
       $result = socket_read($inc, 1024);
   }
   while($result === false); //
 
 
 
Сервер:
$loop = new Socket();
$loop->SocketStart('127.0.0.1', 9876, $maxUsers=100);
$loop->dooo();
 
Класс накопал тут:
http://www.php.ru/forum/viewtopic.php?p=161821&sid=6241bb8317e0170f2a489a3ef8467302#161821
 

 
 
И ещё - как мне запустить "серверную" часть в постоянную работу и как реализуется принудительная пауза или остановка?
 
Спасибо за любую конструктивную помощь.

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 16:37 01-07-2009
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KIVagant

Цитата:
При этом в сетевых соединениях я не вижу, чтобы апач слушал указанный порт.

а почему апач? это php скрипт слушает..
ну, понятно, что раз подключен как модуль, то и, по сути, от апача все делается..

Цитата:
и как реализуется принудительная пауза или остановка?  

пауза или остановка чего?
зачем вы делаете bind у клиента? и при чем там php???
сервер слушает один порт и отвечает на запросы по нему..  
клиент делает коннекты на тот порт и либо держит коннект, либо регулярно запрашивает (это уже аналог ajax)


----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 19:32 01-07-2009
KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Спасибо, Cherry. Поясню: я впервые занялся таким способом обмена данных и для меня ещё некоторые вещи есть лес тёмный и кудристый.
 
Нашел несколько рабочих связок, пример чата.
Также нашел потом ещё пару примеров. Но они написаны без учета, что флеш нынче хочет файл с политикой безопасности.
 
По ссылке выше мне удалось запустить всё это, но отслеживая, как работает флешка, я заметил, что она соединяется, посылает запрос, а затем отключается, если её запускать из браузера в html-странице.
 
Значит, как я понимаю, нужно отправлять ответ. Является ли правильной эта функция и в какой момент нужно отправить такой ответ флешке?  
 

Код:
function read_client($client, $income)
{
   if('<policy-file-request/>'==$income){
       send_MessageOne($client, '<'.'?xml version="1.0" encoding="UTF-8"?'.'>'.
'<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd">'.
'<allow-access-from domain="*" to-ports="*" secure="false" />'.
'<site-control permitted-cross-domain-policies="all" />'.
'</cross-domain-policy>');
   }
}
 
function send_MessageOne($client, $message)
{
    $sendUsers = $message . "\0";
    socket_write($client, $sendUsers);
}

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 09:18 02-07-2009 | Исправлено: KIVagant, 09:24 02-07-2009
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KIVagant

Цитата:
Является ли правильной эта функция и в какой момент нужно отправить такой ответ флешке?

http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html

Цитата:
я впервые занялся таким способом обмена данных и для меня ещё некоторые вещи есть лес тёмный и кудристый

ну так я говорю.. на php создается сервер (вот только если хостинг не ваш - вряд ли кто разрешит демону крутиться там)
flash делает запросы к нему и получает ответы.
то, что вы приводили выше, описывает как раз сервер на php (прослушивание порта 9876)

Цитата:
Клиент:
 
  $s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
   socket_bind($s, '127.0.0.1', 9876); //порты пробовал разные
   socket_listen($s);
   $inc = socket_accept($s);
   socket_set_nonblock($inc);// для множественных подключений, хотя я не совсем ещё разобрался что к чему
   $timeStart = microtime(true);
   do {
       if (5 < microtime(true)-$timeStart) {
           echo 'TIMEOUT';
           break;
       }
       $result = socket_read($inc, 1024);
   }
   while($result === false); //  

 
но, опять же, чем вас http запросы не устраивают?
http://www.wellho.net/mouth/1926_Flash-client-to-PHP-server-example.html
 
но, хотите сокет -  
http://www.kirupa.com/developer/flash8/php5sockets_flash8.htm
http://djz.hu/2007/07/26/php-socket-server-chat-gateway-for-flash-clients/

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 19:39 02-07-2009 | Исправлено: Cheery, 19:39 02-07-2009
KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Спасибо, получилось что-то запустить. Но возник интересный нюанс:
 
я выполняю запрос в браузере, например
http://server:2030/log-clean
этот запрос принимается корректно, обрабатывается, после чего выполняется
@socket_shutdown ( $socket, 2 );
@socket_close ( $socket );
 
В результате, на один запрос браузера, скрипт успевает выполнить сразу несколько подключений-отключений с запрошенным параметром! Почему это происходит?
 

Код:
Array
(
    [0] => Resource id #4
)
num_changed_sockets 1
socket Resource id #4
[2009-07-03 10:57:06] CONNECTED (2/2147483647)
Array
(
    [0] => Resource id #5
)
num_changed_sockets 1
socket Resource id #5
[2009-07-03 10:57:06] LOG CLEAN
[2009-07-03 10:57:06] DISCONNECTED (Resource id #5)
Array
(
    [0] => Resource id #4
)
num_changed_sockets 1
socket Resource id #4
[2009-07-03 10:57:06] CONNECTED (2/2147483647)
Array
(
    [0] => Resource id #6
)
num_changed_sockets 1
socket Resource id #6
[2009-07-03 10:57:06] LOG CLEAN
[2009-07-03 10:57:06] DISCONNECTED (Resource id #6)

 
Добавлено:
Я уже разобрался. Всё дело в провеке  favicon - её через elseif нельзя было делать!
 
Чат заработал на все 100!
 
Добавлено:


Мдаааааа. Только я порадовался чату, как тут же всё и поломалось.  
 
Потратил немыслемую тучу времени, но так и немогу понять следующее:
Есть Class Socket_chat extends Socket_start {}
 
В родительском классе объявлены все необходимые для работы сокета методы.
В наследуемом классе реализованы методы, расширяющие client_listen собственно, обработку входящих данных клиента.
 
Парадокс в следующем:
Socket_chat:

Код:
protected function callback_listen_client($socket, $buffer) {
    $result = $this->call_commands ( $this->read_commands ( &$buffer ), &$socket );
    // КЛЮЧЕВАЯ СТРОКА:
     $this->send_Message ( $this->allclients_ar, &$socket, $buffer );
    }
 

Socket_start:

Код:
protected function send_Message($allclient, $socket, $buf) {
    foreach ( $this->allclients_ar as $client ) {
        $content="[".intval($socket)."]: ".$buf."\n";
        $len=strlen($content);
        $result = socket_write ( $client, $content, $len  );
        print_r($result.": ".$content."\n");
    }
}

 
 
Внимание, вопрос: почему вызов send_Message в $this->call_commands() НИЧЕГО не возвращает, пока я не вызову $this->send_Message() в приведеной первой функции??? Иначе говоря - пока пинка не наподдашь во след - данные во флеш не приходят! Как такой бред может быть?
 
Добавлено:
Ооу, ситуция на самом деле ещё интереснее! Отправляется из любого места, но только если обязательно передаётся $buffer - те же самые данные, что и прислал флеш! Получается, если я не возвращаю флешу его же данные - он ничего не видит!

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 11:59 03-07-2009 | Исправлено: KIVagant, 16:02 03-07-2009
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KIVagant
лучше не поток мыслей, а сформированные вопросы

Цитата:
Внимание, вопрос: почему вызов send_Message в $this->call_commands() НИЧЕГО не возвращает, пока я не вызову $this->send_Message() в приведеной первой функции??? Иначе говоря - пока пинка не наподдашь во след - данные во флеш не приходят! Как такой бред может быть?  

потому что, обычно, команды буферизируются и только потом отправляются

Цитата:
Получается, если я не возвращаю флешу его же данные - он ничего не видит!

наверно вы просто не так все поняли.

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 18:48 03-07-2009
KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Я даже уверен, что не всё так понял, но стоит убрать отправк буффера обратно - и данные тут же перестают приходить. (
Буду пробовать развивать это дело дальше, а там будет видно.

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 09:19 06-07-2009
KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Добрый день всем. Надеюсь, мой сегодняшний пост поможет кому-то не терять лишнего времени.
 
Как я уже давно писал выше, у меня возникала проблема, в результате которой я не мог отправить в сокете с помощью socket_write сообщение клиенту, пока не "проталкивал" его предварительно ответом от самого клиента.
 
То есть, когда я делал так:

Код:
 
// $buffer - это пришло от клиента
// $result - это сформированный ответ клиенту
 
$len=strlen($buffer);
$result = socket_write ( $client, $buffer, $len );
$len=strlen($result);
$result = socket_write ( $client, $result, $len );
 

... то это работало и клиент получал на вывод $result. Но при этом иногда алгоритм сбоил, пакеты путались и я не мог никак понять причины.
После длительных изысканий я сделал следующее -  

Код:
 
$result = socket_write ( $client, $buffer.$result, $len );
 

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

Код:
 
1. Клиент - шлем "test".
2. Сервер - шлем в ответ "{ошибка}"."test".
3. Клиент - получаем и выводим в строку: "test"."{ошибка}".
 

 
И вот это зеркальное отражение и натолкнуло на мысль, что текст "{ошибка}" все-таки берется не из текущего ответа сервера, а из предыдущего! Для проверки я стал нумеровать ответы сервера и догадка подтвердилась. Дальше все просто - я догадался, что в данных клиента (буффере) содержится спец-символ, по которому определяется окончание пакета. Я думал, что за это отвечает socket_write, но оказывается все не так. Проанализировав данные от клиента, я увидел в окончании "\u0000" - то есть "NUL". Языком PHP этот символ можно вывести с помощью "\0". Я стал добавлять этот символ ко всем отсылаемым ответам - и все заработало.
 

Код:
 
$result.="\0";
$len=strlen($result);
$result = socket_write ( $client, $buffer.$result, $len );
 

 
Может для кого-то это есть само собой разумеющееся, но у меня на осознание простой истины ушло очень много бессмысленно потерянного времени.
 
Добавлено:
Кстати, кто может объяснить по-русски разницу между socket_recv() и socket_read(). Какую из них лучше использовать? И для чего используют разные константы, например MSG_WAITALL в socket_recv() или, к примеру PHP_BINARY_READ в socket_read()?
Я нашел в комментариях на php.net интересную функцию, заменяющую стандартный socket_read(,,PHP_NORMAL_READ), но не очень понял - для чего? Может кто по-лучше на буржуйском шпрехает и будет не ленив пояснить? Заранее спасибо.

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 14:29 11-10-2009
KIVagant



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
РЕШЕНИЕ НАЙДЕНО:
 
Почему флешка, которая идеально работает на локалке (127.0.0.1:2040), на сервере упорно не понимает присылаемый ответ с политикой сервера?
 
Вот, что отправляет сервер:

Код:
<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>

Но флешка продолжает спрашивать заново!  
В журнале видно, как флешка постоянно спрашивает файл политики и сервер ей постоянно его отправляет!
 
 
Решение: нефик было делать $bytes = socket_recv( $socket, $buffer, 2048, MSG_WAITALL); Начитался где-то, блин... надо $bytes = socket_recv( $socket, $buffer, 2048, 0);
 
И из-за этой закорлючки бессонная ночь и целый день возни...

Всего записей: 177 | Зарегистр. 08-06-2004 | Отправлено: 14:56 17-10-2009 | Исправлено: KIVagant, 17:12 17-10-2009
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Интернет » Web-программирование » PHP5, AS2 (AS3) Socket


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru