On 13/12/11 17:05, Reid Wightman wrote: > 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 > What happens if you set non-blocking on the socket and try to catch an exception on the recv? require 'fcntl' ... s = UDPSocket.new s.fcntl(Fcntl::F_SETFL, s.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK) ... begin packet, from = s.recvfrom(2048,0) rescue StandardError => e puts "Waarg: #{e}" next end ... Sam