Main > Abyss | PHP > file_get_contents vs CURL

file_get_contents vs CURL

02.02.2013 0 comments » Views: 8,544

PHP

Сегодня столкнулся с проблемой: file_get_contents НЕ использовал указанный мной таймаут для чтение удаленного файла.. Проблема оказалась для меня не столь очевидной, т.к. я её сразу не смог повторить, да что там повторить, я не сразу понял вообще в чем проблема..

Прежде всего было замечено, что скрипт не всегда завершается так, как должен. Я начал дебажить скрипт, и вскоре увидел, что проблема возникает именно в загрузке файлов.

Код для обработки был примерно вот такой:

Во-первых @ помогла пропустить ошибку, но тут её использование было оправдано, т.к. допускались 404 ошибки, и было необходимо  их не писать в логи, а в $data передавать false.

После проведения мной нескольких тестов, оказалось, что file_get_contents попросту не реагирует на указанный мной таймаут, как я думал, это таймаут на соединения И на закачку url...

Я полез в Google и он меня вывел на StackOverflow, вот сюда: PHP file_get_contents ignoring timeout?

Там обсуждалась точно такая же проблема и ей дали объяснение:

You are setting the read timeout with socket_create_context. If the page you are trying to access doesn't exist then the server will let you connect and give you a 404. However, if the site doesn't exist (won't resolve or no web server behind it), then file_get_contents() will ignore read timeout because it hasn't even timed out connecting to it yet.

Вкратце тут говорится, что в случае, если сайт не существует, то file_get_contents игнорирует(!) указанный таймаут, т.к. происходит НЕ таймаут приема данных, а тайм аут соединения с сервером. А file_get_contents НЕ обрабатывает его.

В таких случаях, некоторые советуют менять таймаут сокета:

однако это не приведет к ожидаемому эффекту, т.к. эта настройка служит для работы с медленными соединениями и не имеет отношения к описанной проблеме.

 

Что же делать?

Можно воспользоваться функцией: fsockopen, одним из параметров которой является именно тайм-аут соединения. Как её использовать, это уже ваше дело: можно просто проверить сайт на существование, перед использованием file_get_contents. А можно написать свой file_get_contents используя сокеты. Не так уж это и сложно..

Я же выбираю другой вариант, а именно библиотеку CURL, где все это уже реализовано. Так же советую этот метод и Вам. Код получится примерно такой:

Здесь нет ничего военного:  CURLOPT_TIMEOUT = задает время за которое мы должны загрузить указанный url, а CURLOPT_CONNECTTIMEOUT = задает время на соединение с сервером. Почитать подробнее про параметры можно тут: curl_setopt

Вместо вывода: часто (например, в прототипах) я ленюсь сразу писать нужный код, ведь куда проще написать 1 строчку (file_get_contents) вместо целого метода (CURL или сокеты). Однако как показывает практика, если есть сомнения, лучше потратить сразу 5 минут на написание "правильного метода", чем потом несколько часов вылавливать совсем не очевидный баг. В любом случае, очередная проблема решена, опыт прокачан - УРА!!!!!!

 

Author: | Rating: 4/5 | Tags: ,

Leave a Reply

Your email address will not be published. Required fields are marked *

Allowed HTML-tags: <a>, <code>, <i>, <em>, <strong>, <b>, <u>, <strike>