php сокет сервер

Discussion in 'PHP' started by HugoBorz, 26 Aug 2010.

  1. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Актуальный вопрос на второй странице.
     
    #1 HugoBorz, 26 Aug 2010
    Last edited: 14 Sep 2010
  2. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    HugoBorz http://ru2.php.net/manual/en/sockets.examples.php - ковыряйте этот пример, тут все что вам нужно

    На всякий случай - не все хостинги позволят вам биндить произвольный порт и даже если позволят - не факт, что извне можно будет подключиться
     
    _________________________
  3. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Извиняюсь, что сразу не сообщил. Скрипт сам написан, и хостинг вполне позволяет открывать и конектиться к нему. Суть значит в следующем, после запуска скрипта я конекчусь на нужный порт (всё проходит как и нужно)... далее трабла первая, другой клиент при подключённом первом, соединиться уже не может, ну да ладно это ещё терпимо.... трабла вторая заключается в том, что после того как первый коннект отвалился, второй так и не может соединиться с сервером. В общем сори, что сразу не описал более подробно суть проблемы.
    Собственно сам код
    PHP:
    <?
        
    header('Content-Type: text/plain;');
        
    error_reporting(E_ALL E_WARNING);
        
    set_time_limit(0);
        
    ob_implicit_flush();

        echo 
    "-= Server =-\n\n";

        
    $address 'host';
        
    $port    10001;

        try {

            echo 
    'Create socket ... ';
            if ((
    $sock socket_create(AF_INETSOCK_STREAMSOL_TCP)) < 0) {
                throw new 
    Exception('socket_create() failed: '.socket_strerror(socket_last_error())."\n");
            } else {
                echo 
    "OK\n";
            }

            echo 
    'Bind socket ... ';
            if ((
    $ret socket_bind($sock$address$port)) < 0) {
                throw new 
    Exception('socket_bind() failed: '.socket_strerror(socket_last_error())."\n");
            } else {
                echo 
    "OK\n";
            }

            echo 
    'Listen socket ... ';
            if ((
    $ret socket_listen($sock5)) < 0) {
                throw new 
    Exception('socket_listen() failed: '.socket_strerror(socket_last_error())."\n");
            } else {
                echo 
    "OK\n";
            }

            do {
                echo 
    'Accept socket ... ';
                if ((
    $msgsock socket_accept($sock)) < 0) {
                    throw new 
    Exception('socket_accept() failed: '.socket_strerror(socket_last_error())."\n");
                } else {
                    echo 
    "OK\n";
                }

                
    $msg "Hello, Client!";
                echo 
    "Say to client ($msg) ... ";
                
    socket_write($msgsock$msgstrlen($msg));
                echo 
    "OK\n";

                do {


                    if (
    false === ($buf socket_read($msgsock1024))) {
                        throw new 
    Exception('socket_read() failed: '.socket_strerror(socket_last_error())."\n");
                    } else {

                    }




                    
    $data $buf;
                    
    $filename "text.txt";
                    
    // Если файл существует и в него возможна запись
                    
    if ( is_writeable($filename) ) :
                    
    // Открыть файл и установить указатель текущей позиции в конец файла
                    
    $fh fopen($filename"a+");
                    
    // Записать содержимое $data в файл
                    
    $success fwrite($fh$data);
                    
    // Закрыть файл
                    
    fclose($fh); else :
                    endif;




                    if (!
    $buf trim($buf)) {
                        continue;
                    }

                    if (
    $buf == 'shutdown') {
                        
    socket_close($msgsock);
                        break 
    2;
                    }


                    
    socket_write($msgsock$bufstrlen($buf));


                } while (
    true);

            } while (
    true);

        } catch (
    Exception $e) {
            echo 
    "\nError: ".$e->getMessage();
        }

        if (isset(
    $sock)) {

            echo 
    'Close socket ... ';
            
    socket_close($sock);
            echo 
    "OK\n";

        }
    ?>
    Заранее блогадарен всем, кто поможет в решении данной задачи.
     
    #3 HugoBorz, 26 Aug 2010
    Last edited: 26 Aug 2010
  4. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Большое спасибо, помогло, всё робит. Будем тестить дальше.
     
  5. nf404

    nf404 New Member

    Joined:
    25 Aug 2010
    Messages:
    4
    Likes Received:
    0
    Reputations:
    0
    Смотри в сторону ф-ии socket_select http://www.php.net/manual/en/function.socket-select.php Оа тебе позволит работать с несколькими коннектами.
    Там в юзер каментах есть неплохой пример реализации
     
  6. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Всем кто откликнулся огромно благодарю. Спасибо парни.
    Тему можно закрывать.
     
  7. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Снова поднимаю тему.
    Кто может мне пояснить, в чём заключается проблема. Скрипт написал, коннекты ловит, всё как и полагалось, но работает около 10 минут, потом фиг знает что происходит и приконнектиться нереально. Процесс на серваке так и висит. После убивания процесса, перезапускаю скрипт, процесс запускается а приконнектиться никак, через ~30секунд процесс убиватся. Перезапускаю, история повторяется и так несколько раз. После некоторого секса он всётаки запускается и работает опять как нужно, но опять же непродолжительное время. Поясните плз, кто знает, в чём тут может быть проблема... может в скрипте, может в серваке...?
    Да кст пробовал в крон забить с переодичностью 10 минут, работает чуть дольше но проблемы не решает.
    Собсно код
    PHP:
    <?php
    error_reporting
    (E_ALL);
    ob_implicit_flush();
    $address 'server_ip';
    $port 10000;
    if ((
    $sock socket_create(AF_INETSOCK_STREAMSOL_TCP)) === false) {
        echo 
    "socket_create() failed: reason: " socket_strerror(socket_last_error()) . "\n";
    }
    if (
    socket_bind($sock$address$port) === false) {
        echo 
    "socket_bind() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
    }
    if (
    socket_listen($sock5) === false) {
        echo 
    "socket_listen() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
    }
    do {
        if ((
    $msgsock socket_accept($sock)) === false) {
            echo 
    "socket_accept() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
            break;
        }
        
        
    $msg "\nPHPServer for ZHUK" .
            
    "'quit' OR 'shutdown'.\n";
        
    socket_write($msgsock$msgstrlen($msg));
        do {
            if (
    false === ($buf socket_read($msgsock2048PHP_NORMAL_READ))) {
                echo 
    "socket_read() failed: reason: " socket_strerror(socket_last_error($msgsock)) . "\n";
                break 
    2;
            }
            if (!
    $buf trim($buf)) {
                continue;
            }
            if (
    $buf == '*') {
                break;
            }
            if (
    $buf == 'shutdown') {
                
    socket_close($msgsock);
                break 
    2;
            }

    // тут запись в файл


            
    break;

            
    $talkback "PHP: You said '$buf'.\n";
            
    socket_write($msgsock$talkbackstrlen($talkback));
            echo 
    "$buf\n";
        } while (
    true);
        
    socket_close($msgsock);
    } while (
    true);
    socket_close($sock);
    ?>
     
  8. b3

    b3 Banned

    Joined:
    5 Dec 2004
    Messages:
    2,170
    Likes Received:
    1,155
    Reputations:
    202
    @set_time_limit(0);
    @ini_set('max_execution_time', 0);
     
  9. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    не робит, результат тот же.
     
  10. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    блин, пацаны посоветуйте что нибудь ещё плиз. голова кипит, время идёт, процесс стоит....
     
  11. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    b3 правильно подсказал. Возможно, твой хостинг не поддерживает установки времени максимального выполнения скрипта. Обычно, так оно и есть.
     
  12. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    1gb хост... что можете сказать по этому поводу, или посоветуйте хостинг другой плз
     
  13. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Создай у себя на хостинге PHP файл с таким содержимым:
    PHP:
    <?php
        phpinfo
    ();
    ?>
    И перейди на этот скрипт из браузера. Увидишь где то на странице поле max_execution_time, в котором в секундах написано максимальное время выполнения скрипта. Сможешь узнать хотя бы, действительно ли проблема в хостинге.
     
  14. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    30 написано... это по умолчанию вроде. я жопой чую что проблема в хостинге, но не могу понять именно в чём
    п.с. хотя может и в скрипте косяк... планка съезжает уже может break гдето убрать?
     
    #14 HugoBorz, 4 Sep 2010
    Last edited: 4 Sep 2010
  15. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    всё парни, решил я свою проблему ценой бессонной ночи. проблема была не в хостинге, а именно в скрипте и опредилённых запросах к нему. В общем суть была такая, может комуто помогу. Скрипт работает как нужно, только если запрос на сервак приходит с какимито данными, т.е., благодаря вот этой штуке
    PHP:
    if (!$buf trim($buf)) 
    {             
    continue;         
    }
    пустой запрос или запрос содержащий пробелы, вызывал ступор и коннект так и весел всё время. косяк был исправлен заменой континью на брик, всё летает и обрабатывается как положено.
    Всем кто помогал разобраться респект. Спасибо парни. Всем удачи.
     
  16. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Снова ап.
    В общем проблема в подвисании всей этой ботвы. Всё вроде работало а тут снова таже хрень, даже низнаю что ещё педелать, может кто что посоветует. Значит опишу проблему ещё раз. Запускаю скрипт, процесс висит, всё ровно, все запросы обрабатываются, но в какойто момент, при подключении пишет коннект и всё ждёт, я так понимаю, что скрипт ставит в очередь моё соединение, пока не закроется предыдущее, только трабла в том, что предыдущий запрос обработан и соединение по идеи должно быть закрыто. В чём тут может быть проблема подскажите плиз, а то какой день уже бьюсь, всё никак не выходит.
    PHP:
    <?php
    error_reporting
    (E_ALL);
    /* Allow the script to hang around waiting for connections. */
    @set_time_limit(0);
    @
    ini_set('max_execution_time'0);
    /* Turn on implicit output flushing so we see what we're getting
     * as it comes in. */
    ob_implicit_flush();
    $address 'HOST_IP';
    $port HOST_PORT;
    if ((
    $sock socket_create(AF_INETSOCK_STREAMSOL_TCP)) === false) {
        echo 
    "socket_create() failed: reason: " socket_strerror(socket_last_error()) . "\n";
    }
    if (
    socket_bind($sock$address$port) === false) {
        echo 
    "socket_bind() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
    }
    if (
    socket_listen($sock5) === false) {
        echo 
    "socket_listen() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
    }
    do {
        if ((
    $msgsock socket_accept($sock)) === false) {
            echo 
    "socket_accept() failed: reason: " socket_strerror(socket_last_error($sock)) . "\n";
            break;
        }
        
    /* Send instructions. */
        
    $msg "\nPHPServer." .
            
    "'quit' OR 'shutdown'.\n";
        
    socket_write($msgsock$msgstrlen($msg));
        do {
            if (
    false === ($buf socket_read($msgsock2048PHP_NORMAL_READ))) {
                echo 
    "socket_read() failed: reason: " socket_strerror(socket_last_error($msgsock)) . "\n";
                break 
    2;
            }
            if (!
    $buf trim($buf)) {
                break;
            }
            if (
    $buf == '*') {
                break;
            }
            if (
    $buf == 'shutdown') {
                
    socket_close($msgsock);
                break 
    2;
            }

                
    $data $buf;

    ЗДЕСЬ ПИШЕМ ЗАПРОС В ФАЙЛ

            
    break;

            
    $talkback "PHP: You said '$buf'.\n";
            
    socket_write($msgsock$talkbackstrlen($talkback));
            echo 
    "$buf\n";
        } while (
    true);
        
    socket_close($msgsock);
    } while (
    true);
    socket_close($sock);
    ?>
     
  17. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    Посмотрите этот пример. http://ru2.php.net/manual/en/function.socket-select.php#56241 Это простенький многопользовательский чат. Правда в таком виде он будет нещадно грузить проц, поэтому в функции socket_select четвертым параметром пропишите 120

    А в вашем коде проблема, имхо, в PHP_NORMAL_READ - пхп в блокирующем режиме ожидает символ перевода строки. Попробуйте исправить на PHP_BINARY_READ, но тут вы встретите другую проблему, если обращаетесь к скрипту не с помощью других скриптов
     
    _________________________
    #17 Gifts, 14 Sep 2010
    Last edited: 14 Sep 2010
  18. HugoBorz

    HugoBorz New Member

    Joined:
    19 Apr 2009
    Messages:
    23
    Likes Received:
    0
    Reputations:
    0
    Я пробовал ваш пример ещё ранее и действительно процессор нагружало не хило, поставил 120 вместо 0, проц теперь не грузит, но сам процесс вылетает всёравно, примерно секунд 30-40 робит и всё. Что можете подсказать по этому поводу? Может какимто образом можно решить проблему с символом перевода строки, так как в бинарном режиме для моей задачи решение не подходит. И остаётся ещё вопрос, по какой причине процесс может закрываться. Иногда работает долго и всё в порядке, а бывает процесс падает через несколько минут работы.
     
    #18 HugoBorz, 14 Sep 2010
    Last edited: 14 Sep 2010
  19. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    HugoBorz Прочитайте какую-нибудь книгу про клиент-серверное программирование/проектирование.

    Если ваш скрипт работает, а скрипт по моей последней ссылке - нет, то попробуйте добавить в него строки:
    PHP:
    @set_time_limit(0);
    @
    ini_set('max_execution_time'0); 
    Создайте буфер, в который будут складываться принятые данные, если в новой порции есть символы \r \n - то отправляете/обрабатывайте данные вплоть до этого знака, и соответственно удаляете их из буфера.
    Возможно, проблема еще в этой строке: false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ)

    Попробуйте заменить эти строки:
    PHP:
            if (false === ($buf socket_read($msgsock2048PHP_NORMAL_READ))) {
                echo 
    "socket_read() failed: reason: " socket_strerror(socket_last_error($msgsock)) . "\n";
                break 
    2;
            }
            if (!
    $buf trim($buf)) {
                break;
            } 
    На эти:
    PHP:
    $buf socket_read($msgsock2048PHP_BINARY_READ);
    if (
    $buf === false || strlen($buf)<1) {
    break;
    }
    И вместо socket_close($msgsock); написать if ($msgsock) socket_close($msgsock);

    Ну и если проблема не в ошибках скрипта, то вариантов - куча. Например, на время работы может влиять способ запуска (из браузера/из коммандной строки), сервер может выгружать скрипты, при превышении использования памяти на аккаунт и так далее. Проще связаться с тех. поддержкой хостинга и спросить, какие их настройки могут влиять на данный скрипт
     
    _________________________
    #19 Gifts, 14 Sep 2010
    Last edited: 14 Sep 2010
  20. nf404

    nf404 New Member

    Joined:
    25 Aug 2010
    Messages:
    4
    Likes Received:
    0
    Reputations:
    0
    В общем опишу основные проблемные места.

    1. работа осуществляется с блокируемыми сокетами. Это означает что пока у тебя полностью не отработает одно соединение второе принять нельзя. Т.е. немогут одновременно подцепиться 2 клиента. Сильно рекомендую использовать неблокируемые сокеты. Для этого после socket_accept нужно делать socket_set_nonblock и разруливать чтение из сокетов через socket_select.

    2. Если всё-таки собираешься юзать блокируемые сокеты, то тебе потребуется stream_set_timeout.

    3. Проверку на чтение из блокируемого сокета лучше всего реализовать через stream_get_meta_data

    4. socket_write может вернуть ошибку. обрабатывать её тоже неплохо бы.


    Будут ещё вопросы - в ПМ, легко отвечу. Много собак съел))))