Working with TCP Sockets 読書メモ 目次
タイムアウト
使用できない選択肢
- Ruby組み込みの
timeout
ライブラリはソケットと同時に使うのに適していない SNDTIMEO
/RCVTIMEO
とソケットオプションの組み合わせも理想的ではない
IO.select
IO.select
はタイムアウトにも使うことができる
require 'socket'
require 'timeout' # Timeout::Error を使うためにrequire
timeout = 5 # seconds
Socket.tcp_server_loop(4481) do |connection|
begin
# 最初のread(2)を実行する
# すでにデータがある状態で select(2) を実行するのを避けるため
connection.read_nonblock(4096)
rescue Errno::EAGAIN
# 読み込み可能になるまでモニターする
if IO.select([connection], nil, nil, timeout)
# IO.select がnilを返さなかった => ソケットは読み込み可能
retry
else
puts 'timeout'
raise Timeout::Error
end
end
connection.close
end
acceptのタイムアウト
server = TCPServer.new(4481)
timeout = 5 # seconds
begin
server.accept_nonblock
rescue Errno::EAGAIN
if IO.select([server], nil, nil, timeout)
retry
else
raise Timeout::Error
end
end
connectのタイムアウト
require 'socket'
require 'timeout'
socket = Socket.new(:INET, :STREAM)
remote_addr = Socket.pack_sockaddr_in(80, 'google.com')
timeout = 5 # seconds
begin
socket.connect_nonblock(remote_addr)
rescue Errno::EINPROGRESS
if IO.select(nil, [socket], nil, timeout)
retry
else
raise Timeout::Error
end
rescue Errno::EISCONN
# connectが正常に完了
end
socket.write('hi')
socket.close