Определить в php-скрипте, если он подключен к Интернету?

Как я могу проверить, подключен ли я к Интернету из моего PHP-скрипта, который работает на моей машине разработки?

Я запускаю скрипт для загрузки набора файлов (которые могут существовать или не существовать) с помощью wget. Если я попытаюсь загрузить без подключения, wget переходит к следующему, думая, что файла нет.


person Steve    schedule 01.02.2011    source источник


Ответы (11)


Вы всегда можете пропинговать старый добрый гугл:

$response = null;
system("ping -c 1 google.com", $response);
if($response == 0)
{
    // this means you are connected
}
person Gabi Purcaru    schedule 01.02.2011
comment
Это вполне надежно, но имейте в виду, что ICMP работает != работает TCP (что с брандмауэрами, NAT и прочим), и даже работает TCP != работает HTTP (прозрачные прокси и т.д.). - person Piskvor left the building; 01.02.2011

Этот код не работал в среде php laravel 4.2 с внутренней ошибкой сервера 500:

<?php
     function is_connected()
     {
       $connected = @fsockopen("www.some_domain.com", 80); 
        //website, port  (try 80 or 443)
       if ($connected){
          $is_conn = true; //action when connected
          fclose($connected);
       }else{
         $is_conn = false; //action in connection failure
       }
      return $is_conn;
    }
?>

Что я не хотел напрягать, чтобы понять это, поэтому я попробовал этот код, и он сработал для меня:

function is_connected()
{
  $connected = fopen("http://www.google.com:80/","r");
  if($connected)
  {
     return true;
  } else {
   return false;
  }

} 

Обратите внимание: это основано на предположении, что подключение к google.com менее подвержено сбоям.

person user28864    schedule 16.01.2015
comment
Хорошая альтернатива! Это также требует allow_url_fopen = On в php.ini - person zanderwar; 06.08.2019
comment
В моих тестах fopen в два раза медленнее, чем альтернатива fsockopen. Кроме того, этот синтаксис выглядел бы лучше, чем уродливый if() с возвратом true/false: return (bool) fopen(google.com:80/,r); - person aFeijo; 15.01.2020

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

if(!$sock = @fsockopen('www.google.com', 80))
{
    echo 'Not Connected';
}
else
{
echo 'Connected';
}
person hilbiazhar    schedule 17.02.2016

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

С другой стороны, вы также можете использовать функции curl в php, а затем вы можете сделать все отслеживание ошибок из PHP.

person wimvds    schedule 01.02.2011

Существуют различные факторы, определяющие подключение к Интернету. Состояние интерфейса, например. Но, несмотря на это, из-за характера сети правильная конфигурация не означает, что у вас есть работающее соединение.

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

Попробуйте выбрать один из них на целевом хосте. Если это невозможно, выберите какой-нибудь крупный веб-сайт, например Google или Yahoo.

Наконец, просто попробуйте проверить код ошибки, возвращаемый wget. Бьюсь об заклад, они разные для 404-х и тайм-аутов. Вы можете использовать третий параметр в вызове exec:

string exec (string $command [, array &$output [, int &$return_var]])

person Maciej Łebkowski    schedule 01.02.2011

Также обратите внимание, что fopen и fsockopen различны. fsockopen открывает сокет в зависимости от префикса протокола. fopen открывает файл или что-то еще, например файл через HTTP, фильтр потока или что-то еще и т. д. В конечном итоге это влияет на время выполнения.

person John Katieno    schedule 18.09.2020

Вы можете пропинговать популярный сайт или сайт, с которого вы получаете запрос (например, www.google.nl), а затем проанализировать результат, чтобы увидеть, можете ли вы подключиться к нему.

<?php
$ip = '127.0.0.1'; //some ip
exec("ping -n 4 $ip 2>&1", $output, $retval);
if ($retval != 0) { 
echo "no!"; 
} 
else 
{ 
echo "yes!"; }
?>
person Roy T.    schedule 01.02.2011
comment
За исключением того, что на самом деле не делайте это по IP-адресу. - person Ignacio Vazquez-Abrams; 01.02.2011
comment
А почему бы не использовать какой-нибудь IP? Это именно то, что происходит за кулисами при использовании некоторого домена. - person killstreet; 07.12.2016
comment
@killstreet с использованием полного доменного имени — это более разумное кодирование, благодаря которому вы можете обновить DNS без необходимости обновлять свой код. - person zanderwar; 06.08.2019

Просто проверьте результат wget. Код состояния 4 указывает на проблему с сетью, код состояния 8 указывает на ошибку сервера (например, 404). Это работает, только если вы вызываете wget для каждого файла последовательно, а не один раз для всех файлов.

Вы также можете использовать libcurl с PHP вместо вызова wget. Что-то типа:

foreach (...) {
    $c = curl_init($url);
    $f = fopen($filepath, "w")
    curl_setopt($c, CURLOPT_FILE, $f);
    curl_setopt($c, CURLOPT_HEADER, 0);
    if (curl_exec($c)) {
        if (curl_getinfo($c, CURLINFO_HTTP_CODE) == 200) {
            // success
        } else {
            // 404 or something, delete file
            unlink($filepath);
        }
    } else {
        // network error or server down
        break; // abort
    }
    curl_close($c);
}
person Dietrich Epp    schedule 01.02.2011

Эта функция обрабатывает то, что вам нужно

function isConnected()
{
    // use 80 for http or 443 for https protocol
    $connected = @fsockopen("www.example.com", 80);
    if ($connected){
        fclose($connected);
        return true; 
    }
    return false;
}
person Lost Koder    schedule 14.01.2017

Вы можете использовать это, добавив это внутри класса:

private $api_domain  = 'google.com';

private function serverAliveOrNot()
{
    if($pf = @fsockopen($this->api_domain, 443)) {
        fclose($pf);
        $_SESSION['serverAliveOrNot'] = true;
        return true;
    } else {
        $_SESSION['serverAliveOrNot'] = false;
        return false;
    }
}
person codelone    schedule 02.06.2021

person    schedule
comment
+ Хороший ответ: кто-то другой может подумать, что [80|443] будет переключаться между любыми портами... :) - person Baba; 05.04.2013
comment
На основе этого сообщение, вероятно, имеет смысл использовать example.com в качестве www.some_domain.com ответа. - person nzn; 02.02.2016