За последние 24 часа нас посетили 24430 программистов и 1656 роботов. Сейчас ищут 958 программистов ...

Перезапустить Websocket

Тема в разделе "PHP для новичков", создана пользователем Griffter, 9 ноя 2017.

  1. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Всем добрый день!
    C Websocket`ами ранее не работал, но вот появилась в них необходимость...Есть у меня websocket, который тянет данные с биржи (получается я выступаю в качестве клиента). Эти данные передаются часами, намеренно соединение никогда не закрывается. Но иногда скрипт останавливается спустя там 10, 20 часов по неизвестным причинам(может сам сервер прекратил работу, может мой клиент где-то затупил).
    Суть самого вопроса: Можно ли как-то отследить, что соединение до сих пор открыто или что скрипт еще отрабатывается? Если связь по вебсокету прервана, то нужно его перезапустить.
    Дайте пожалуйста совет, как это правильно делается.
     
  2. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    а код клиента то покажи, телепатов нема....
    так-то при разрыве коннекта событие есть
     
  3. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    подпишусь на ответы)) интересно)) сейчас как раз ковыряю вебсокеты))
     
  4. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Использовался https://github.com/Devristo/phpws
    Код подключения:
    PHP:
    1. <?php
    2. define('ROOT', dirname(__FILE__));
    3. require_once(ROOT.'/vendor2/autoload.php');                // Composer autoloader
    4. require_once (ROOT.'/pushService/Bitfinexpush.php');
    5. $loop = \React\EventLoop\Factory::create();
    6.  
    7. $logger = new \Zend\Log\Logger();
    8. $writer = new Zend\Log\Writer\Stream("php://output");
    9. $logger->addWriter($writer);
    10.  
    11. $client = new \Devristo\Phpws\Client\WebSocket("wss://api.bitfinex.com/ws/2", $loop, $logger);
    12.  
    13. $bitfinex = new Bitfinexpush();
    14.  
    15. $client->on("request", function($headers) use ($logger){
    16.     $logger->notice("Request object created!");
    17. });
    18.  
    19. $client->on("handshake", function() use ($logger) {
    20.     $logger->notice("Handshake received!");
    21. });
    22.  
    23. $client->on("connect", function($headers) use ($logger, $client){
    24.     $logger->notice("Connected!");
    25.     $client->send('{"event":"subscribe","channel":"candles","key":"trade:5m:tBTCUSD"}');
    26. });
    27.  
    28. $client->on("message", function($message) use ($client, $logger){
    29.     $msg = $message->getData();
    30.     $bitfinex->getData($msg);
    31. });
    32.  
    33. $client->open();
    34. $loop->run();
     
  5. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    попробуй посмотреть метод getState()
    ну или подпишись на чего-нить такое
    PHP:
    1. $client->on("close", function($message) use ($client,$logger){
    2. });
     
    Griffter нравится это.
  6. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Да, всё верно, такой метод есть. Можно проверять типа:
    PHP:
    1.     if($client->getState() == 2){
    2.         $client->open();
    3.     }
    Это в том случае, если сервер мне закрыл соединение... А вот если скрипт к примеру завершился ошибкой, как его заново запустить?
    Смотрю сейчас в сторону этого. Чтобы крон к примеру каждый час проверял, и по надобности перезапускал скрипт.
    PHP:
    1. $lockFile = __FILE__.'.lock';
    2. $hasFile = file_exists($lockFile);
    3. $lockFp = fopen($lockFile, 'w');
    4.  
    5. // Если блокировку получить не удалось, значит второй скрипт еще работает
    6. if (!flock($lockFp, LOCK_EX | LOCK_NB)) {
    7.     die('Sorry, one more script is running.');
    8. }
    9.  
    10. // Если файл блокировки уже существовал, но не был залочен,
    11. // значит предыдущий запуск завершился некорректно
    12. if ($hasFile) {
    13.     echo 'The previous running has been completed with an error.';
    14. }
    15.  
    16. // Все в порядке, блокировка lock получен
    17.  
    18. // По окончании работы необходимо снять блокировку и удалить файл
    19. register_shutdown_function(function() use ($lockFp, $lockFile) {
    20.     flock($lockFp, LOCK_UN);
    21.     unlink($lockFile);
    22. });
    Такой подход еще актуален? или возможно есть новые методики уже?
     
    #6 Griffter, 9 ноя 2017
    Последнее редактирование: 9 ноя 2017
  7. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    чет велосипед какой то с файлами то...
    в каком смысле скрипт завершился? Исключение какое то сработало? или че - может в эту сторону копать?
     
  8. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Да, по поводу велосипеда согласен) просто ничего адекватного больше не нашел...
    Нет, исключений нет. На данном этапе я явно понимаю, что мне сам сервер оборвал соединение, в этом случае решение с методом getState() вполне подходит. Но заглядывая немного наперед, возможен же такой момент, что к примеру сервер к которому я обращаюсь за данными вовсе не отвечает, упал на какое-то время. И в этой ситуации скорей всего getState я не получу, верно? Как тогда можно перезапускать скрипт до того момента, пока сервер мне не ответит?
     
  9. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    запусти на локалке - отруби инет и посмотри че будет)
    --- Добавлено ---
    именно с этой библой не работал, но на ratchet когда делал, а клиента на js
    там явно всегда срабатывало onclose .... просто код завершения менялся
    типа например 1000 был - некорректное завершение - тогда по таймеру запускали проверял
    а при другом статусе - который обозначал что серв сам корректно просто со мной завершил сеанс - типа выдавал сообщение - что сервер недоступен и кнопель- попробовать еще - ну а там все ясно
     
    Griffter нравится это.
  10. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Гениально)) Да, сработало исключение
    Код (Text):
    1. 2017-11-09T16:50:59+03:00 ERR (3): exception 'RuntimeException' with message 'Unable to connect to DNS server:
    Да тут тоже есть статусы есть 0,1,2,3. 1 - соединение установлено, 2 - соединение закрыто, 3 - соединение еще не установлено. Это как я понял.
    Вот меня этот тонкий момент и интересует. У вас к примеру кнопка была, чтобы переподключиться, а вот как бы мне переподключаться? Можно к примеру отлавливать исключение, что сервер лежит сейчас, и опять перезапускать скрипт. Но тогда получится что я так сказать "в рекурсии" будут гонять этот скрипт и бессмысленно ломиться на сервер часами... sleep на некоторое время делать что ли, чтобы хоть раз в 5 минут делать подключение? Или это в корне не правильное решение?
     
  11. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    ну не знаю....... я бы постепенно увеличивал интервалы просто
    типа через минуту, еще минуту, 5, 10,20, час , сутки )))
     
    Griffter нравится это.
  12. Griffter

    Griffter Новичок

    С нами с:
    27 сен 2017
    Сообщения:
    92
    Симпатии:
    25
    Хорошо, спасибо за помощь! Пока других идей нет, буду этим велосипедом пользоваться))