2015-06-11 3 views
1

Intro

У меня есть клиент, который делает многочисленные подключения SSL к сторонней службе. В некоторых случаях сторонняя сторона перестает отвечать на запросы во время процесса сокета и ssl. Когда это происходит, моя текущая реализация «сидит» в течение нескольких часов подряд до истечения времени.Неблокирующее согласование сокетов SSL в Ruby. Возможное?

Для борьбы с этим, я пытаюсь выполнить следующий процесс:

require 'socket' 
require 'openssl' 

# variables 

host = '....' 
port = ... 
p12 = #OpenSSL::PKCS12 object 

# set up socket 

addr = Socket.getaddrinfo(host, nil) 
sockaddr = Socket.pack_sockaddr_in(port, addr[0][3]) 

socket = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0) 
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) 

begin 
    socket.connect_nonblock(sockaddr) 
rescue IO::WaitWritable 
    if IO.select(nil, [socket], nil, timeout) 
    begin 
     socket.connect_nonblock(sockaddr) 
    rescue Errno::EISCONN 
     puts "socket connected" 
    rescue 
     puts "socket error" 
     socket.close 
     raise 
    end 
    else 
    socket.close 
    raise "Connection timeout" 
    end 
end 

# negotiate ssl 

context  = OpenSSL::SSL::SSLContext.new 
context.cert = p12.certificate 
context.key = p12.key 

ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, context) 
ssl_socket.sync_close = true 

puts "ssl connecting" 
ssl_socket.connect_nonblock 
puts "ssl connected" 

# cleanup 

ssl_socket.close 
puts "socket closed" 

ssl_socket.connect_nonblock будет в конечном счете, завернутый в аналогичной структуре, как socket.connect_nonblock есть.

Проблема

Проблема Я бегу в том, что ssl_socket.connect_nonblock вызывает следующее при запуске:

`connect_nonblock': read would block (OpenSSL::SSL::SSLError) 

Вместо этого, я бы ожидать, что это поднимет IO::WaitWritable, как socket.connect_nonblock делает.

Я просмотрел интернет для получения информации об этой конкретной ошибке, но не могу найти что-либо особого использования. Из того, что я собираю, другие успели использовать этот метод, поэтому я не уверен, что мне не хватает. Для полноты я нашел те же результаты как с ruby ​​2.2.0, так и с 1.9.3.

Любые предложения приветствуются!

ответ

2

Имейте такую ​​же проблему, я попробовал ниже, кажется, работает правильно для моей ситуации.

ssl_socket = OpenSSL::SSL::SSLSocket.new socket, context 
ssl_socket.sync = true 

begin 
    ssl_socket.connect_nonblock 
rescue IO::WaitReadable 
    if IO.select([ssl_socket], nil, nil, timeout) 
    retry 
    else 
    # timeout 
    end 
rescue IO::WaitWritable 
    if IO.select(nil, [ssl_socket], nil, timeout) 
    retry 
    else 
    # timeout 
    end 
end 
Смежные вопросы