ost*_*lli 6 ruby sockets openssl bidirectional two-way
我正在构建一个客户端Ruby库,它连接到服务器并等待数据,但也允许用户通过调用方法来发送数据.
我使用的机制是有一个初始化套接字对的类,如下所示:
def initialize
@pipe_r, @pipe_w = Socket.pair(:UNIX, :STREAM, 0)
end
Run Code Online (Sandbox Code Playgroud)
我允许开发人员调用以向服务器发送数据的方法如下所示:
def send(data)
@pipe_w.write(data)
@pipe_w.flush
end
Run Code Online (Sandbox Code Playgroud)
然后我在一个单独的线程中有一个循环,我从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
Run Code Online (Sandbox Code Playgroud)
这样可以很好地工作,但只能TCPSocket按照例子的正常情况进行.我需要使用一个OpenSSL::SSL::SSLSocket,但是根据IO.select文档:
使用IO.select的最佳方法是在非阻塞方法(如read_nonblock,write_nonblock等)之后调用它.
[...]
特别是,非阻塞方法和IO.select的组合对于像OpenSSL :: SSL :: SSLSocket这样的IO对象是首选的.
根据这个,我需要IO.select 在非阻塞方法之后调用,而在我的循环中我之前使用它,所以我可以从2个不同的IO对象中进行选择.
有关如何使用IO.selectSSL套接字的给定示例是:
begin
result = socket.read_nonblock(1024)
rescue IO::WaitReadable
IO.select([socket])
retry
rescue IO::WaitWritable
IO.select(nil, [socket])
retry
end
Run Code Online (Sandbox Code Playgroud)
但是,这仅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
Run Code Online (Sandbox Code Playgroud)
这看起来并不那么糟糕,但欢迎任何输入.
我不熟悉 ruby 本身,但不熟悉将 select 与基于 SSL 的套接字一起使用的问题。SSL 套接字的行为与 TCP 套接字不同,因为 SSL 数据以帧形式传输,而不是作为数据流传输,但流语义仍然应用于套接字接口。
让我们用一个例子来解释这一点,首先使用一个简单的 TCP 连接:
对于 SSL,情况有所不同:
如何处理这种差异: