I need to make a UDP server that waits for clients to log on and then drives
communication from the server side. This means that if a client doesn't ack
subsequent comms from the server, the server needs to resend those
comms a few times before giving up.
I have gotten as far as a successful UDP server, but it blocks the thread
forever, and having a server constantly breaking out of
socket.recvfrom using Timeout
does not seem to work at all (port never seems open). I need a UDP wait
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
···
From: "Leslie Viljoen" <leslieviljoen@gmail.com>