Ruby中的非阻塞SSL套接字协商。可能?

时间:2015-06-11 17:25:16

标签: ruby sockets ssl openssl connection-timeout

简介

我有一个客户端,可以与第三方服务建立大量SSL连接。在某些情况下,第三方在套接字和ssl协商过程中停止响应。发生这种情况时,我的当前实现会在超时前“持续”数小时。

为了解决这个问题,我正在尝试实施以下过程:

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.01.9.3中找到了相同的结果。

非常感谢任何建议!

1 个答案:

答案 0 :(得分: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