我正在构建一个连接到服务器并等待数据的客户端Ruby库,但也允许用户通过调用方法发送数据。如何在Ruby中创建双向SSL套接字
我用的机制是有初始化一个插口对一类,像这样:
def initialize
@pipe_r, @pipe_w = Socket.pair(:UNIX, :STREAM, 0)
end
,我允许开发人员调用将数据发送到服务器的方法是这样的:
def send(data)
@pipe_w.write(data)
@pipe_w.flush
end
然后,我有一个单独的线程,其中,I从连接到所述服务器的socket
选择一个循环,并从@pipe_r
:
def socket_loop
Thread.new do
socket = TCPSocket.new(host, port)
loop do
ready = IO.select([socket, @pipe_r])
if ready[0].include?(@pipe_r)
data_to_send = @pipe_r.read_nonblock(1024)
socket.write(data_to_send)
end
if ready[0].include?(socket)
data_received = socket.read_nonblock(1024)
h2 << data_received
break if socket.nil? || socket.closed? || socket.eof?
end
end
end
end
这个工程很漂亮,但只有正常TCPSocket
根据示例。我需要使用OpenSSL::SSL::SSLSocket
代替,但是按照the IO.select docs:
的最佳方式使用IO.select是非阻塞的方法,如read_nonblock,write_nonblock,等以后调用它
[...]
特别是,对于IO类对象(如OpenSSL :: SSL :: SSLSocket),非阻塞方法和IO.select的组合更受欢迎。
根据这一点,我需要调用IO.select
后非阻塞的方法,而在我的循环我用它之前,所以我可以从2个不同的IO对象选择。
如何使用IO.select
使用SSL插座给出的例子是:
begin
result = socket.read_nonblock(1024)
rescue IO::WaitReadable
IO.select([socket])
retry
rescue IO::WaitWritable
IO.select(nil, [socket])
retry
end
但是只有IO.select
使用带有单 IO对象这部作品。
我的问题是:鉴于我需要从@pipe_r
和socket
对象中进行选择,我怎样才能让我的上一个示例使用SSL套接字?
编辑:我试过什么@ steffen-ullrich建议,但无济于事。我能够使我的测试通过使用以下内容:
loop do
begin
data_to_send = @pipe_r.read_nonblock(1024)
socket.write(data_to_send)
rescue IO::WaitReadable, IO::WaitWritable
end
begin
data_received = socket.read_nonblock(1024)
h2 << data_received
break if socket.nil? || socket.closed? || socket.eof?
rescue IO::WaitReadable
IO.select([socket, @pipe_r])
rescue IO::WaitWritable
IO.select([@pipe_r], [socket])
end
end
这看起来并不坏,但任何输入是受欢迎的。
谢谢@斯蒂芬 - 乌尔里希,这是一个非常明确的答复。不幸的是,我在使用select之前试过使用pending方法,我总是得到0字节可用。我也尝试了nonblock_read(32768),这也不是绝招。将尝试更多。 – ostinelli
会接受这个答案,因为它阐明了解决这些问题的正确方法。再次感谢你! – ostinelli