From: “Leslie V.” [email protected]
with a timeout.
I have looked at several UDP examples, and tried the sparse docs here:
http://ruby-doc.org/stdlib/libdoc/socket/rdoc/classes/Socket.html#M004528
- but no luck yet. I tried recvfrom_nonblock as a guess but it seems to
block anyway.
Over the years, I’ve never been 100% successful getting nonblock
semantics to work with UDP sockets on ruby. I end up with code like:
require ‘timeout’
require ‘fcntl’
UDP_RECV_TIMEOUT = 0.5 # seconds
…
begin
timeout(0.17) {
sock = UDPSocket.open
if defined? Fcntl::O_NONBLOCK
if defined? Fcntl::F_GETFL
sock.fcntl(Fcntl::F_SETFL, sock.fcntl(Fcntl::F_GETFL) |
Fcntl::O_NONBLOCK)
else
sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
end
end
n = sock.send(cmd, 0, @server_addr, @server_port)
}
rescue Timeout::Error
File.open(“error.log”, “a”) {|f| f.puts “[#{Time.now}] q2cmd:
timeout in UDP open/send”}
end
if select([sock], nil, nil, UDP_RECV_TIMEOUT)
begin
# note, some linux kernel versions will select() positive for
a UDP
# packet, but the packet has a bad checksum, and when we do
recvfrom()
# the packet is thrown out, and we are blocked. (I think, due
to ruby’s
# internals, even though we’re setting NONBLOCK here, doesn’t
help,
# for some reason… i think this was explained on ruby-talk.)
# Thus the ‘timeout’.
timeout(0.17) {
resp = sock.recvfrom(65536)
}
rescue Timeout::Error
$stdout.puts “q2cmd: Timeout::Error in sock.recvfrom !”
end
end
. . . and it still blocks occasionally, even though the socket is
in nonblocking mode.
I’m currently rewriting one of my UDP apps using eventmachine
http://rubyeventmachine.com/ … which presumably will solve
the blocking issue.
Regards,
Bill