Есть потребность уведомлять пользаков по аське. Есть хороший классец для этих целей. Он работает, но напрягает что при завершении скрипта коннект с Аськой обрывается и в следующий раз нужно занаво переподключаться. Повторные подключения естественно не моментальны и эти задержки очень заметны для пользователей. Как решить эту проблему?
Делаем скрип-сервер, которому передаём данные (текст сообщения) через сокет. Сам скрипт коннектится к ICQ и в бесконечном цикле слушает сокет, если обнаруживает подключение - принимает данные и рассылает пользователям.
Пример сервера, допускающего подключение к себе нескольких клиентов: PHP: <?php // Set time limit to indefinite execution set_time_limit(0); // Set the ip and port we will listen on $address = '127.0.0.1'; $port = 9000; $max_clients = 10; // Array that will hold client information $clients = Array(); // Create a TCP Stream socket $sock = socket_create(AF_INET, SOCK_STREAM, 0); // Bind the socket to an address/port socket_bind($sock, $address, $port) or die('Could not bind to address: '.$address); // Start listening for connections socket_listen($sock); // Loop continuously while (true) { // Setup clients listen socket for reading $read[0] = $sock; for ($i = 0; $i < $max_clients; $i++) { if ($clients[$i]['sock'] != null) $read[$i + 1] = $clients[$i]['sock']; } // Set up a blocking call to socket_select() $null=null; $ready = socket_select($read,$null,$null,$null); /* if a new connection is being made add it to the client array */ if (in_array($sock, $read)) { for ($i = 0; $i <= $max_clients; $i++) { if ($clients[$i]['sock'] == null) { $clients[$i]['sock'] = socket_accept($sock); break; } elseif ($i == $max_clients) { socket_close($clients[$i]['sock']); unset($clients[$i]); break; } } if (--$ready <= 0) continue; } // end if in_array // If a client is trying to write - handle it now for ($i = 0; $i < $max_clients; $i++) // for each client { if (in_array($clients[$i]['sock'] , $read)) { while ($input .= socket_read($clients[$i]['sock'],128)) { if(substr_count($input,"\r\n")) { $input=str_replace("\r\n",null,$input); break; } } if ($input == 'Bye!' or $input == null) { // String meaning disconnected unset($clients[$i]); } elseif ($input == 'exit') { // requested disconnect socket_close($sock); die; } else { // strip white spaces and write back to user $output = $input."\r\n"; socket_write($clients[$i]['sock'],$output); } $input=null; } elseif (key_exists($i,$clients)) { // Close the socket socket_close($clients[$i]['sock']); unset($clients[$i]); } } socket_set_block($sock); } // end while // Close the master sockets socket_close($sock); ?> Получая строку Bye или пустую строку, он закрывает соеденение с клиентом, получая строку exit - завершает работу. После 18-й строки можешь вставить подключение к ICQ, а в блоке else, который начинается с 69-й строке, рассылку сообщения ($input).
http://wip.asminog.com/releases/WebIcqPro1.2b.tar.gz В архив включен пример простого робота. Читайте README сначала.
WebIcqPro я знаю. как раз им и пользовался. хороший класец. но как я писал внутри скрипта неудобно его использовать. а сокеты на ПХП юзать тяжело. нет хороших классов- оберток. А писать стабильный сокет- сервер таким вот макаром тяжеловато. есть же ПХП- шные проекты, которые рассылают асю тоннами. должен значит быть какой- то готовый сервер с админкой и класс для работы с ним из ПХП. 2 alBoo: сколько секунд у тебя выполняется подключение к аське при помощи этого класса?
без понятия он один раз коннектится и висит демоном, периодически проверяя в БД новые данные для отправки. находит, отправляет, дальше висит пока не убьеш или !stop не напишеш ему
Сокеты на PHP работают очень даже неплохо, если не полениться, то можно очень хорошую систему разработать. Есть, они подключаются, рассылают, и отключаются.
2 alBoo: я сразу не понял как он работает. только теперь дошло. то есть команды серверу передаются опять же через асю. это как раз готовый сервер со своеобразной админкой. это очень- очень подходит. просто как все гениальное. спасибо! еще бы довести это до такого уровня, считай продукт мирового уровня получится. Код (Text): $sender= new ICQMessageSender($uin, $password, $adminUin, $messageStack); $sender->start(); $messageStack - любая реализация fifo стэка, которая в клиентском скрипте кидает новое сообщения в копилку сообщений, а на стороне сендера достает их оттуда. Мне лично нужен постгресовский стэк сообщений, который бы их не удалял после извлечения, кому то из e-mail ящика, кому то из файла или еще как. это уже кому как надо, сам напишет и подключит его к твоему классу. нет ли у тебя желания дописать такой вот сендер? будет просто круть тогда отправить сообщение из моего скрипта будет всего Код (Text): $messageStack= new PostgresStack(); $messageStack->push(123456, 'hello!');
2 vs да я не говорю что они работают плохо. просто они пока без классов. юзать тяжеловато. будут классы с событиями и исключениями- будем юзать только в путь! как тебе идея сендера? две строчки кода и сообщение отправлено. никаких тебе задержек и сокетов. по- моему вариант.
или вот вариант: обернуть твой сокет- сервер в обертку до уровня. серве естественно внутри коннектит один раз WebIcqPro и написать к такому серверу звонилку типа Код (Text): $message= new ICQMessage($uin, $body); $message->send(); а в сенде коннект по сокету к твоему серверу. опять же если это все с корректной обработкой всех исключений, переподключения да плюс события на стороне сервера OnConnect(), OnSend($uin, $body) и т.д. тогда тоже вариант. еще какой. только здесь один момент. если в первом случае с копилкой сервак не работает или аська не подключается, то задержек в прикладном скрипте не будет. это очень важно. а в твоем случае с сокетами по- моему во время подключения к неработающему серверу опять будут задержки по несколько секунд. или я ошибаюсь?
WebICQpro это одновременн сокет-сервер и клиент. Разница с моим вариантом лишь в том, что управление им осуществляется с помощью той же icq. Вопрос стоял вначале о постоянн запущенно icq-клиенте, соответственно, ему надо как-то передавать данные в режиме реального времени, а делать это можно только через сокеты, при чем для этого скрипт icq-клиент надо интегрировать с сокет-сервером.
нет не только через сокеты. можно кидать все сообщения из прикладного скрипта в некую копилку как alBoo если проверять копилку даже раз в минуту, получается близко к режиму реального времени, а если уж совсем реалтайм нужен, можно проверять копилку раз в секунду. нет ли у тебя желания обернуть твой сервер в простой для использования класс?