Демон чата: PHP или C ???

borzih2

Новичок
Демон чата: PHP или C ???

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

На каком языке делать демона? PHP или C? Очень хотелось бы на PHP. И код писать проще (а значит ошибок меньше допускать), и с MySQL легко связываться, но вопрос "производительности" заставляет задуматься...

Был создан "тестовый демон" на PHP. При нагрузке в 100 онлайн пользователей - 75% загрузки процессора (Intel Pentium IV 3000 МГц). Расход памяти - несколько мегабайт. В основе кода лежит примерчик от young (Alexander Voytsekhovskyy). Вот полный текст кода:

PHP:
<? 

// **************************************************************************
// Основные константы
// **************************************************************************

define("HOST", "111.222.33.44"); // Хост (IP) для прослушки
define("PORT", "1234");          // Прослушиваемый порт
define("DALAY", 100000);         // Кол-во милесекунд между проверками
define("MAX_KEEP_ALIVE", 600);   // Макс. время, позволенное быть без активности

// **************************************************************************
// Класс, занимающийся обработкой конкретного клиента 
// **************************************************************************

class phpServerThread { 

    // Минимальная информация, необходимая для описания одного клиента
    // ---------------------------------------------------------------

    var $socket;       // Сокет соединения
    var $buffer;       // Временный буфер для чтения команд
    var $lastActivity; // Время последней активности клиента

    // Конструктор клиента (вызывается в момент его коннекта)
    // ------------------------------------------------------
     
    function phpServerThread($socket) { 
        $this->socket = $socket;          // Запоминаем сокет
        $this->buffer = '';               // Обнуляем буффер
        $this->lastActivity = time();     // Дата активности
        $this->response("Hello, user!");  // Отправляем ответ пользователю
    } 

    // Отправить клиенту сообщение. $mess - текст сообщения.
    // -----------------------------------------------------
     
    function response($mess) { 
        //$mess = str_replace("\n","",$mess);
        //$mess = str_replace("\x00","",$mess);
        $mess = $mess."\n\x00"; 
        socket_write($this->socket, $mess, strlen($mess)); 
    } 
 
    // Уничтожить клиента
    // ------------------
    
    function destroy() { 
        @socket_close($this->socket); 
    } 
} 

// **************************************************************************
// Начальная инициализация
// **************************************************************************

$sock = socket_create(AF_INET, SOCK_STREAM, 0) or die("Error");
socket_bind($sock, HOST, PORT)                 or die("Error");
socket_listen($sock, 20)                       or die("Error");
socket_set_nonblock($sock)                     or die("Error");
     
$pool = array(); 

echo "Demon is started!\n";

// **************************************************************************
// Вечный цикл прослушки
// **************************************************************************

while(1) { 

  usleep(DELAY); 
           
  // Принимаем клиентов, которые стоят в очереди 
  $currentTime = time(); 
  if(($msgsock = @socket_accept($sock))) { 
    socket_set_nonblock($msgsock); 
    $pool[] = & new phpServerThread($msgsock); 
    echo "New client is connected! Number of clients: ".count($pool)."\n";
  } 
             
  // Обслуживаем клиентов 
  foreach($pool as $key => $client) { 
                 
    // Читаем все что они хотят сказать 
    if($tmp = @socket_read($pool[$key]->socket, 1024)) { 
      $pool[$key]->buffer .= $tmp; 
      $pool[$key]->lastActivity = $currentTime; 
    } 
                                 
    // Если в буфере есть законченая фраза - обрабатываем 
    if($pos = strrpos($pool[$key]->buffer, "\n")) { 
      $toSay = substr($pool[$key]->buffer, 0, $pos);
      $pool[$key]->buffer = substr($pool[$key]->buffer, $pos + 1); 
      echo "User command is: ".$toSay."\n";
      user_command($key, $toSay);
    } 

    // Соединение завершено клиентом ИЛИ превышено время ожидания?
    if($tmp==="" || $currentTime - $pool[$key]->lastActivity > MAX_KEEP_ALIVE) {
      $pool[$key]->destroy(); 
      unset($pool[$key]); 
      echo "Client is DIE! Number of clients: ".count($pool)."\n";
    }

  } 

} 

// **************************************************************************
// Функция обработки команд от Флешки
// **************************************************************************

// $client -  клиент, который подал команду
// $command - текст команды

function user_command($client, $command) {

  global $pool;  // Тут живут клиенты

  $a = 2*(int)$command;
  $pool[$client]->response($a);

}

?>
Нет ли в этом коде какой-нибудь страшной ошибки, из-за которой возникает такая страшная загрузка процессора лишь при 100 пользователях ???
 

borzih2

Новичок
Автор оригинала: kruglov
Есть, конечно.
DALAY != DELAY
Гениально!!! Сейчас исправлю и заново запущу тестирование! Если кому интересно, напишу и о новых результатах... Большое спасибо!!!
 

borzih2

Новичок
Превосходно! 200 пользователей онлайн - всего 2% CPU и 4 Мб памяти!!! И кто тут только говорил, что на PHP демоны чата не пишутся?! :)
 

Krishna

Продался Java
+ Уже был топик ровно с таким вопросом.
В Поиск, в правила, марш отсюда! =)
 

monah

Новичок
блин, народ а не просветите, как демон на php работает? А то ищу, чёт никак найти не могу.
Сам скрипт не в боузере ведь запускать надо? Да и на открытие порта, простого хостинга маловато, наверно... Как че работает я понимаю прекрасно, я не понимаю как именно это запустить... Надо сервак снимать, или под это есть специальный хостинг? С финансовой точки зрение запуск демона на php чем то отличается от аналогичных на обычных языках?
 

ONK

Пассивист PHPСluba
monah, Демон на ПХП по способам использования ничем не отличается от демона написанного на любом другом языке программирования.
На ПХП вполне спокойно можно написать HTTP сервер с моделью работы как у Apache 1.3х и даже более продвинутые варианты, поддерживающие обработку сигналов ОС + разветвление совмещённое с мультиплексированием для обработки соединений.

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

WP

^_^
borzih2
Это делает админ)

Написал на PHP класс http демона, и на нем чат сделал - доволен. Многопоточный =) Главное - не накосячить с памятью, т.к. например foreach делает копию массива, и жрет память дико, если в цикле.

http://88.212.221.3:31332/httpreqinfo
 

WP

^_^
nerezus
Поднял)

-~{}~ 11.01.07 12:58:

Кстати, usleep(DELAY); хреновый выход из положения. Т.к. мы просто каждую операцию (accept/read) тупо ждем. И если утилиткой ab послать пару тыщ запросов будут большие лаги из-за sleep. Поэтому я сделал так что если нагрузка есть (в предыдущую итерацию цикла была выполнена какая-то операция, то не ждем, а если мы находимся в простое то usleep, и само значение балансируется). Тесты показали что при большой нагрузке нет лагов, а при простое не жрется процессор.

А также я думаю над многопоточностью (pcntl_fork), лишним не будет, естественно в новые потоки отдавать обработку запросов. Вдруг будут долгие запросы..
 

phprus

Moderator
Команда форума
WP
Вы будете распространять этот класс демона? А то интересно было бы посмотреть как он работает.
 

WP

^_^
ONK
_http://xengine.whitephoenix.ru/ru/chat/

-~{}~ 12.01.07 18:19:

з.ы. я там в данный момент балуюсь так что чат выключается.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Автор оригинала: WP
Написал на PHP класс http демона, и на нем чат сделал - доволен. Многопоточный =)
Покажи пожалуйста пример реализации многопоточности?
 
Сверху