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[3]
          type, block, data = scan_packet(packet)
          break if (type == OP_ERROR) || (type == OP_OPACK) || ((type ==
OP_ACK) && (block == seq))
        end
      end

My output is:
<I see the write request packet go out via wireshark>
<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
slow).

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
behavior.

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?

Thanks,
Reid

-- 
Posted via http://www.ruby-forum.com/.