Blocking UDP recv() interaction with select()

M

Mark Zvilius

I want to use Ruby for a UDP server application under Windows XP. I
intend to use two threads: one for a simple UI, and a separate thread
for the UDP server (with blocking calls).

As a proof of concept I wrote the following test code, whose intent is
to wait for an incoming message, with the user able to press CTRL-C to
terminate the “server.â€

---------------------
# server thread
def bar
sock = UDPSocket.new()
sock.bind( "", PORT )
begin
msg, adr = sock.recvfrom(256)
rescue Interrupt
puts "interrupt"
else
print adr.inspect, " -> ", msg.inspect, "\n"
end
sock.close
end

# main (ui) thread
t = Thread.new( &method:)bar) )
puts "press ctrl-c to quit"
begin
select( nil, nil, [STDIN], 1.0 ) while t.alive?
rescue Interrupt
t.raise( Interrupt )
end
puts "wait for thread"
t.join()
puts "thread reaped"
---------------------

This approach works great for handling CTRL-C: the application exits
without hesitation.

However there are 2 problems:

1. When I send a message to the server, I get the following error on the
select() call:
C:/bin/ruby/z.rb:54:in `select': An operation was attempted on something
that is not a socket. (Errno::ENOTSOCK)

2. While waiting with one thread at the recvfrom() and the other in the
one-second select() loop, this code uses 100% of the available CPU time.

Are these considered bugs, features, or perhaps bugs that are not
fixable? [I am fully aware that Winsock select() only works for sockets,
so the underlying implementation must be nastier for Windows than for
Unix.]

Is there a more appropriate way to provide a “UI thread†alongside a
blocking UDP server thread?

I am using Ruby 1.8.5 on Windows XP.

Thanks,
Mark Zvilius
 
B

Bill Kelly

From: "Mark Zvilius said:
1. When I send a message to the server, I get the following error on the
select() call:
C:/bin/ruby/z.rb:54:in `select': An operation was attempted on something
that is not a socket. (Errno::ENOTSOCK)

2. While waiting with one thread at the recvfrom() and the other in the
one-second select() loop, this code uses 100% of the available CPU time.

Your code calling select with STDIN on Windows isn't going to
work properly. Here's what I get in IRB:
select( nil, nil, [STDIN], 1.0 )
Errno::ENOTSOCK: An operation was attempted on something that is not a socket.
from (irb):174:in `select'
from (irb):174

It seems this has changed from the old behavior, which, if I recall
correctly, didn't used to raise an exception. I think it used to just
always immediately return from select indicating the file handle
was readable (regardless of whether any data was present or
not.)

But anyway...

I don't have a particular suggestion, other than to only use sockets
with select on Windows.

If you need to check whether any input has arrived at the console,
I've used 'kbhit' in the past.

( http://groups.google.com/group/comp.lang.ruby/msg/27eaefd419457a5f )


Hope this helps,

Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top