Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Серверные технологии и Flash (http://www.flasher.ru/forum/forumdisplay.php?f=62)
-   -   Производительность и выносливость php, сокеты (http://www.flasher.ru/forum/showthread.php?t=146273)

Ralph_DiMarko 02.11.2010 23:45

Производительность и выносливость php, сокеты
 
добрый вечер!
Меня седня оч сильно огорчили и хочу знать правда ли это.
Делаю чат с наворотами для проекта. Создал сокет в пхп и слушаю определенный порт.
PHP код:

socket create
socket bind
socket listen 

и потом
PHP код:

while(true){
   
//ловлю изменения и реагирую на них


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

Очень хотелось бы услышать ваши мысли из опыта, какие пределы и особенности у пхп. Что на нем можно писать а что нет, какой язык популярен для сервера. Кстати собирался писать по такому же принципу и сервер для MMO. Я три месяца с пхп и это мой первый опыт работы с сокетами. Буду весьма благодарен за помощь и направление.

membrilius 03.11.2010 00:12

у меня отлично работал..

висел на VPS ... запускался из командной строки и был засунут в автозагрузку.. т.к. сервер раз в сутки перезагружался.
Обращение к БД было только когда конектился новый пользователь. (проверка логина пароля, и вытаскивание персонального конфига)

Все данные хранились в массивах

по такой схеме $array_chat['user'][$client]['name']

id юзера, id_ресурс сокета и инфа

сообщения я вообще не хранил, получал и сразу рассылал

Вообще простейщая схема такая:

Код:

set_time_limit(0);
ob_implicit_flush();

require_once "mysql.php";

echo "- Сервер <br /><br />";

$array_chat['name_room']['1'] = "общая комната";

$address = gethostbyname('localhost');
$port = 4679;

echo "Создание сокета ... ";
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if($socket < 0)
{
        echo "Ошибка: ".socket_strerror(socket_last_error())."<br />";
}
else
{
        echo "OK <br />";
}

echo 'Устанавливаем опцию сокета SO_REUSEADDR ... ';
if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1))
{
        print('ERROR: socket_create() failed: '.socket_strerror(socket_last_error())."<br>");
}
else
{
        echo "OK<br>";
}

socket_set_nonblock($socket);

echo "Привязывание сокета... ";
$bind = socket_bind($socket, $address, $port);
if($bind < 0)
{
        echo "Ошибка: ".socket_strerror(socket_last_error())."<br />";
}
else
{
        echo "OK <br />";
}

echo "Прослушивание сокета... ";
$listen = socket_listen($socket, 5);
if($listen < 0)
{
        echo "Ошибка: ".socket_strerror(socket_last_error())."<br />";
}
else
{
        echo "OK <br />";
}

$array_sockets = array($socket);

while(true)
{
        $read = $array_sockets;

        // смотрим изменение на сокетах (чтение)
        if (socket_select($read, $write = NULL, $except = NULL, 1, 0) > 0)
        {
                foreach($read as $client)
                {                                                       
                        if(!array_search($client, $array_sockets))
                        {
                                echo "Подключился новый человек... <br />";

                                $client = socket_accept($socket);

                                if($client < 0) continue;
                               
                                $array_sockets[] = $client;
                        }

                        $msg = socket_read($client, 1024);

                        if(!$msg)
                        {
                            // значит человек вышел, удаляем данные из массивов, закрываем его сокет.
                        }
                        else
                        {
                            // тут ловим сообщения от клиентов и выполняем соответствуюшие действия
                        }
              }
      }
}

if (isset($socket))
{
        echo "Закрываем соединение... ";
        socket_close($socket);
        echo "OK <br />";
}

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

Ralph_DiMarko 03.11.2010 10:22

У меня почти что аналогичная схема работы, т.е. логика работы такая же.
Цитата:

остальное сразу отправляется и удаляется из памяти.
Это автоматом удаляется или вручную как то нужно удалять из памяти?

membrilius 03.11.2010 12:26

просто unset на элемент массива.. или переменную, PHP должен выгружать из памяти

Ralph_DiMarko 04.11.2010 10:20

membrilius спасибо.

А кто-то писал что-то более серьезное на пхп, чем чат? может какие то ММО игры?

Dimitry_II 04.11.2010 20:28

Сразу оговорюсь - огромный, мягко говоря, НЕсторонник ПэХаПэ ...

Нюансы работы с подобного рода серверных языков заключаются в работе сокетов, точнее, в том, что это обычные блокирующие сокеты: открывается сокет, он висит в памяти сервера (!) и закрывается при обрыве или соответствующей команде. При этом по разным источникам "вес" открытого сокета в памяти сервера составляет от 400Кб до 2Мб. Отсюда ограничение - максимальное количество открытых одновременно сокетов составляет сотни (о тысячах нигде не слышал).

Альтернативой блокирующим сокетам выступают НЕблокирующие советы (NIO sockets), работа которых основана на событийной модели работы платформы. С точки зрения бизнес-логики это сложнее среде, но зато позволяет работать с количеством коннектов, как минимум, на порядок выше, чем при блокирующих сокетах (когда занимался близко этой темой, сталкивался с упоминаниями о тесте в 20 тыс. одновременных коннектов к отдельному серверу, что в принципе невозможно при блокирующих сокетах).

Фактически это единственное ограничение, которое накладывает работа в ПэХаПэ - невозможность создавать неблокирующие сокеты. В остальном существенной разницы не замечено (из публикаций).

membrilius 04.11.2010 21:16

Dimitry_II

тогда что делают следующие функции:

socket_set_block - переводит сокет в режим блокировки, в это режиме операции ввода-вывода ожидают завершения запросов.

socket_set_noblock - переводит сокет в незаблокированый режим работы, в этом режиме операции ввода-вывода осуществляются немедленно, даже если данные не могут быть переданы.

altermann 05.11.2010 19:26

Написал я сокет сервер для мультипользовательской игры на пыхе, теперь мучаюсь.
Может, конечно, я что не так понаписал, тем не менее, примерно при 25 одновременных коннектах порт отваливается и усе, перестает что либо принимать, такое чувство, что скрипт вылетает. Смотришь процессы - висит.... пока скрипт сервака не перезагрузишь, проблема не решиться.

Сейчас быстро изучаю smartfoxserver.... вот такие проблемки бывают с php

membrilius 05.11.2010 21:49

господа, запомните, ПХП это интерпретатор ... написанный на Си .. и теоретически он может тоже самое, только + к нагрузке идёт распознание кода и перевод его в аналог на СИ...

ДА падает производительность, да не для ИРГ .. но чат написать запросто.

а данный момент он работе быстрее PERL и Python ... а скоро выйдет PHP6 ... в котором убран весь мусор, и идёт расчет только на производительность.

Ralph_DiMarko 05.11.2010 23:15

У меня тоже отваливается, причем бывает что даже когда никого нет в чате, при это не выдавая никаких ошибок.
А смартфокс не дешево стоит, а те 20 онлайн юзеров которые бесплатно предлагает смартфокс, можно и на пхп обеспечить :)


Часовой пояс GMT +4, время: 06:21.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.