Проверить, существует ли интернет-соединение с Ruby?

Просто спросил, как проверить, существует ли интернет-соединение с использованием javascript, и получил несколько отличных ответов. Как проще всего это сделать в Ruby? Пытаясь сделать сгенерированный код разметки html как можно более чистым, я хотел бы условно отображать тег скрипта для файлов javascript в зависимости от того, есть ли интернет-условие. Что-то вроде (это HAML):

- if internet_connection?
    %script{:src => "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", :type => "text/javascript"}
- else
    %script{:src => "/shared/javascripts/jquery/jquery.js", :type => "text/javascript"}

person Lance Pollard    schedule 05.03.2010    source источник
comment
возможный дубликат Проверка подключения к Интернету   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 23.09.2014
comment
@CiroSantilli указанный вами вопрос старше, но он лучше сформулирован и имеет значительно лучшие ответы ...   -  person Brad Werth    schedule 25.09.2014
comment
@BradWerth, какой бы из них мы ни обманули, меня устраивает;) Я думаю, что другой так же хорош, поскольку контекст здесь мало что добавил к моему пониманию: я прочитал один лайнер из другого вопроса и понял тот же вопрос.   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 25.09.2014


Ответы (6)


Вы можете использовать класс Ping.

require 'resolv-replace'
require 'ping'

def internet_connection?
  Ping.pingecho "google.com", 1, 80
end

Метод возвращает true или false и не вызывает исключений.

person Simone Carletti    schedule 05.03.2010
comment
Почему необходимо требовать «resolv-replace»? Кроме того, из стандартной библиотеки 1.9 был удален «пинг». Я придумал достаточно простую работу вокруг здесь... но если есть лучший способ сделать это для 1.9, дайте мне знать. - person Myron Marston; 21.09.2010
comment
Это не правильно. Брандмауэр может блокировать ICMP, и в этом случае будет возвращено значение false. Но интернет-соединение может быть в порядке. - person Mark Thomas; 03.04.2014
comment
Это самый идеальный способ? Я имею в виду, как Windows узнает, должен ли я войти в Wi-Fi? Они пингуют некоторые серверы? (это совершенно не в тему) - person Rishav; 02.03.2018

require 'open-uri'

def internet_connection?
  begin
    true if open("http://www.google.com/")
  rescue
    false
  end
end

Это ближе к тому, что ищет ОП. Он работает в Ruby 1.8 и 1.9. Это тоже немного чище.

person MrKrisF    schedule 29.11.2011
comment
+1 У меня была похожая потребность, и это было лучшее И самое лаконичное решение. - person allesklar; 28.02.2012
comment
Проблема с этой командой в том, что она может блокироваться на долгое время, если соединение неустойчивое, а добавление :read_timeout не всегда надежно: open("http://www.google.com", { read_timeout: 5 } ) может блокироваться более 5 секунд. - person Dirty Henry; 29.05.2014
comment
Прямо сейчас, с моим грязным подключением к Интернету: помещает Benchmark.measure { open(google.com, { read_timeout: 5 } ) } выходы 0,010000 0,000000 0,010000 ( 35,588267) => ноль - person Dirty Henry; 29.05.2014

Мне нравится, как все просто предполагают, что серверы Google работают. Кредиты для Google.

Если вы хотите узнать, есть ли у вас интернет, не полагаясь на Google, вы можете использовать DNS, чтобы узнать, можете ли вы установить соединение.

Вы можете использовать Ruby DNS Resolv, чтобы попытаться перевести URL-адрес в IP-адрес. Работает для Ruby версии 1.8.6+

So:

#The awesome part: resolv is in the standard library

def has_internet?
  require "resolv"
  dns_resolver = Resolv::DNS.new()
  begin
    dns_resolver.getaddress("symbolics.com")#the first domain name ever. Will probably not be removed ever.
    return true
  rescue Resolv::ResolvError => e
    return false
  end
end

Надеюсь, это кому-нибудь поможет :)

person Automatico    schedule 03.04.2014
comment
Или используйте icann.org. Если это устаревает, то DNS и Интернет устаревают в основном. - person Automatico; 03.04.2014
comment
Получение IP-адреса не означает, что IP-адрес доступен. - person Mark Thomas; 03.04.2014
comment
Хорошее замечание по поводу icann.org. Я думаю, что еще одна причина, по которой люди по умолчанию используют Google, заключается в том, что он быстрее отвечает на контент. Хотя запрос HTTP HEAD был бы даже быстрее и, ИМХО, было бы лучшим решением. - person Mark Thomas; 03.04.2014
comment
@MarkThomas Речь идет о проверке наличия подключения к Интернету, а не о проверке того, подключен ли какой-либо конкретный сервер к сети. - person Automatico; 03.04.2014
comment
Конечно, вы можете просто пропинговать корневые серверы DNS (am).root-servers.net. Если все они не работают, у нас проблемы. - person Automatico; 03.04.2014
comment
Да, корневые серверы — это хорошая идея, я просто не стал бы использовать ICMP (ping), потому что он иногда блокируется корпоративными брандмауэрами. - person Mark Thomas; 03.04.2014
comment
Это работало, когда ни один из других не работал, за исключением медленного метода open-uri. СПАСИБО - person boulder_ruby; 23.01.2015
comment
Действительно действенный способ. - person Rishav; 02.03.2018

Те же основы, что и в ответе Симоне Карлетти, но совместимы с Ruby 2:

# gem install "net-ping"

require "net/ping"

def internet_connection?
  Net::Ping::External.new("8.8.8.8").ping?
end
person fguillen    schedule 09.07.2015
comment
Та же система, что и в моем инструменте pet interneeee - person fguillen; 09.07.2015
comment
Еще один более эффективный способ, чем принятый ответ. Использует меньшую полосу пропускания. - person Rishav; 02.03.2018

Пытался найти решение проблемы похожей на вашу и не нашел. К сожалению, метод Ping.pingecho у меня не работает по неизвестной мне причине. Я придумал решение. Последний способ сделать это с помощью httparty. Я хотел это в модуле, и я сделал это так, и он отлично работает.

# gem install httparty
require "httparty"

module Main
  def Main.check_net
    begin
      a = HTTParty.get("https://www.google.com")
      if a.length() >= 100
        puts "online"
      end
    rescue SocketError
      puts "offline"
    end
  end
end

include Main
Main.check_net

Ошибка сокета для Google может не произойти, поэтому этот метод будет работать.

person bit817    schedule 08.07.2021

def connected?
  !!Socket.getaddrinfo("google.com", "http")  
rescue SocketError => e
  e.message != 'getaddrinfo: nodename nor servname provided, or not known'
end

Поскольку он использует имя хоста, первое, что ему нужно сделать, это поиск DNS, что вызывает исключение, если нет подключения к Интернету.

person Kris    schedule 03.04.2014
comment
Часто запросы DNS кэшируются на локальном сервере; это не гарантирует, что Интернет доступен. - person Mark Thomas; 03.04.2014
comment
Конечно возможность. - person Kris; 03.04.2014
comment
@MarkThomas Тот же аргумент можно использовать для самой веб-страницы. Часто на самих маршрутизаторах есть CDN-серверы и, возможно, кэши. А как насчет стран, которые блокируют google.com? Единственный верный способ узнать это — подключиться к серверу, которым вы владеете, который имеет некоторые зависящие от времени данные, которые он передает вам, которые вы можете проверить локально, а затем вы только знаете, что у вас есть доступ к этому серверу. Я знаю, что DNS более распространен, но я просто говорю, что может происходить и множество других вещей. - person Automatico; 03.04.2014
comment
Хотя верно то, что существует много потенциальных переходов, маршрутизаторов, кэшей, CDN и т. д., из-за которых трудно определить, в какой момент вы подключаетесь к Интернету, я бы определенно сказал, что разрешение DNS — это слишком ранний процесс. Очень часто, когда сеть не работает, DNS все еще не разрешается. - person Mark Thomas; 03.04.2014