& - PullRequest
       0

&

1 голос
/ 10 февраля 2020

Я работаю над следующей задачей, чтобы выяснить информацию о сертификате домена по URL, используя библиотеки сокетов OpenSSL, TCPSocket и TCP. В настоящее время я пытаюсь улучшить существующий процесс, используя библиотеку потоков для подключения к сокету и возврата информации. По большей части код, кажется, работает только с точки зрения скорости. Однако я получаю неточные результаты и не знаю, почему. Я не очень хорошо разбираюсь с потоками, TCPSockets или OpenSSL и, кроме того, я думаю, что сочетание этих библиотек / классов способствует этим ошибкам. Вот код, который у меня есть.

Код ниже - это класс, который я использую для проверки связи с URL-адресом и получения информации о его сертификате.

class SslClient
  attr_reader :url, :port, :timeout

  def initialize(url, port = '443', timeout = 10)
    @url = url
    @port = port
    @timeout = timeout
  end

  def ping_for_certificate_info
    context = OpenSSL::SSL::SSLContext.new
    certificates = nil
    verify_result = nil
    Timeout.timeout(timeout) do
      tcp_client = TCPSocket.new(url, port)
      ssl_client = OpenSSL::SSL::SSLSocket.new tcp_client, context
      ssl_client.hostname = url
      ssl_client.sync_close = true
      ssl_client.connect
      certificates = ssl_client.peer_cert_chain_with_openssl_extension
      verify_result = ssl_client.verify_result
      tcp_client.close
    end
    {certificate: certificates.first, verify_result: verify_result }
  rescue => error
    puts error.inspect
  end
end

Код ниже является сокращенным версия того, как мой код использует SslClient для записи информации:

    domains.map do |url|
      Thread.new do
        ssl_client = SslClient.new(struct.domain.gsub("*.", "www."), url.scan_port)
        cert_info = ssl_client.ping_for_certificate_info

        if cert_info
          #### Does some if logic for the cert ######
        else
         ###### Does some else logic for the cert, etc. ######
        end
      end
    end.map(&:value)

    #### Do more stuff ######

Когда я запускаю код как есть, я получаю следующую ошибку:

#<Timeout::Error: execution expired>

Если я увеличу аргумент времени ожидания через SslCient до чего-то смешного, например 30 секунд, я получаю следующую ошибку: #<SocketError: getaddrinfo: Temporary failure in name resolution>

Если бы я получил список 20 лучших веб-сайтов и запустил код с тайм-аутом, установленным на 30, только несколько доменов будут возвращать SocketError, и он варьируется от 3 ошибок сокетов до примерно 8. Однако в более ранней и более медленной версии без многопоточности вся информация о домене проверяется в чистоте и точности. Я не уверен, почему это так.

Возможно ли, что Нить как-то связана с этой проблемой? Или, может быть, я закрываю связь «чтобы быстро»? Я пытался исследовать код по частям, и я подозреваю, что поток является проблемой. Однако я не уверен в том, почему это может быть проблемой из-за того, что я прочитал, что потоки являются стандартными для работы API / внешних вызовов. Кто-нибудь есть рекомендации, которые я мог бы попытаться решить эту проблему? Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...