@accountnujen

Как можно установить время неответа на CURLOPT_WRITEFUNCTION?

Есть ip, который постоянно (каждые 5 секунд), отвечает в виде потока. Это камера, которая информирует о новых видео. Функция writer поддерживает эти ответы, а handler обрабатывает ответ. Мне нужно, чтобы этот запрос выполнялся вечно, однако в какой-то момент, как, к примеру, сейчас, камера может перестать вообще отвечать. Свет выключили либо ещё что-то случилось, но сейчас я не могу обратиться по ip. В обычном состоянии камера постоянно отвечает:
--myboundary
Content-Type: text/plain
Content-Length: 9
Heartbeat

Что означает, что новых видео нет. На данных момент логах у меня зафиксировано последнее время и ответ, когда запустился writer и всё.

Как мне можно установить какой-нибудь ограничитель, чтобы он срабатывал в случае если ответа нет в течении условных 20 секунд? По сути, за это отвечает TIMEOUT, однако скрипт перестанет выполняться через 20 секунд, даже если ответы во writer были, поэтому сейчас установлен 0. Нужен другой ограничитель.

function writer($ch, $data) {
  handler($data);
  return strlen($data);
}

$ch = curl_init("$urlcam/cgi-bin/eventManager.cgi?action=attach&codes=[NewFile]&heartbeat=5");
curl_setopt_array($ch, [
        CURLOPT_USERPWD => "$user:$pass",
        CURLOPT_CONNECTTIMEOUT => 20,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_HTTPAUTH=>CURLAUTH_DIGEST,
        CURLOPT_CUSTOMREQUEST => "GET",
        CURLOPT_WRITEFUNCTION => 'writer'
    ]);

$result = curl_exec($ch);
curl_close($ch);
  • Вопрос задан
  • 73 просмотра
Пригласить эксперта
Ответы на вопрос 2
@alexalexes
У вас callback в виде функции writer скорее всего не срабатывает, в случае ошибки по curl.
Попробуйте проанализировать curl после посылки запроса:
$result = curl_exec($ch);
$info = curl_getinfo($ch);
if($info['http_code'] != 200)
{
  // по http не получили статус 200, значит, пишем репорт об этом
}
curl_close($ch);

Вариант 2:
$result = curl_exec($ch);
$curl_error_number = curl_errno($ch);
if($curl_error_number)
{
   $info = curl_getinfo($ch);
  // что-то случилось с соединением в целом, пишем репорт об этом со сведениями $info
}
curl_close($ch);
Ответ написан
gzhegow
@gzhegow
aka "ОбнимиБизнесмена"
Вы решаете задачу потокового получения данных разовым запросом к камере.

Потоковое получение данных это когда ты используешь fsockopen() или socket_create() в этом случае ты "подписываешься" на камеру и ловишь весь траффик, который оттуда приходит. И это соединение само по себе сломается, если камера перестала отвечать.

Под капотом оно работает как опросник на уровне операционной системы, который с некой частотой проверяет информацию в ячейке памяти.

Так как вы делаете тоже можно, но ваш вызов надо заворачивать в

while (true) {
  // > запрос (сам по себе займет несколько секунд, если повезет - меньше секунды, таймауты в этом случае нужны чтобы при проблемах сети, но когда все устройства работают - немножко подождать, секунду-полторы, а не 20)

  // где-то тут брать значение счетчика microtime(true) и писать функцию считающую разницу по вашим критериям, будь это 20 сек с последнего запроса или 20 сек с последних полученных данных

  usleep(1); // подождать минимум 1 микросекунду (1 кадр), позволив этому ядру проверить другие ожидающие задачи операционной системы, чтобы процессор не задымился от 100% нагрузки в случае если запрос перестанет происходить
  // usleep можно ставить и больше, например 1*1E5 или 100 000, это 100 мс, но в принципе операционке достаточно 1 кадр, она все равно вернется только после того как закончит проверку всех устройств, т.е. по факту пройдет не 1 мкс, а "минимум 1 мкс".
}


но правильно, это все таки подключится сокет соединением на порт камеры.

И нет, этот скрипт не нужно потом запускать из браузера. Он запускается из командой строки/total_commander вызовом "php index.php", что приведет к запуску окошка в котором он работает. Из браузера что-то с while (true) запустишь и оно рано или поздно сляжет по php execution time.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы