Hi all -
I’m extremely new to Ruby programming. Forgive me.
I’m trying to develop an updated Net::TFTP library. The existing
library doesn’t seem to work correctly with the few embedded devices
that I’ve tried it with. It’s quite old and uses Timeout::timeout()
while waiting on IO, and this never, ever seems to work (timeout
exception is always thrown, whether I am writing or reading).
I’ve been rewriting the library to use IO.select() in place of all of
the old Timeout::timeout() statements. I’m finding that its behavior is
really weird, though.
Here is my snippet of modified Net::TFTP.putbinaryfile:
def putbinary(remotefile, io, &block) # :yields: data, seq s = UDPSocket.new peer_ip = IPSocket.getaddress(@host) puts "putting binary file to ", peer_ip peer_tid = nil seq = 0 from = nil data = nil while TRUE do s.send(wrq_packet(remotefile, "octet"), 0, peer_ip, @port) puts "(Re-)Sent fwrite request, waiting for response" a = IO.select([s], nil, nil, 1) if a puts "." packet, from = s.recvfrom(2048,0) puts "." puts "received packet " , packet, " from ", from next unless peer_ip == from type, block, data = scan_packet(packet) break if (type == OP_ERROR) || (type == OP_OPACK) || ((type ==
OP_ACK) && (block == seq))
My output is:
<0.04 seconds later, I see an ACK from the tftp server>
Sent fwrite request, waiting for response
<The program then pauses for 5 seconds>
received packet…yadda yadda yadda
The same delay occurs when I actually send packets of the file (and if
the file is big, the 5-second delays between blocks is horrifyingly
It seems that recvfrom() still blocks, even though IO.select should not
return a non-nil response unless there is data to be read on the socket?
Setting different maximum sizes to recvfrom() doesn’t change the
I wrote a separate program doing the exact same thing with IO.select()
followed by recvfrom(). It then s.send()'s the data back to the client,
basically making a UDP echo service. Connecting to that with netcat
yields exactly what I’d expect: the data is echo’d back to netcat
immediately, not after a several-second delay.
If it’s any help, I’m running Ruby 1.8.7…
I’d appreciate any help that folks can provide, even if it’s just a
pointer to some other documentation that I should read. From what I’ve
read, IO.select() should do what I want, though?