How to get the Windows handle for a socket

On Windows, I do the following (trying to get a nonblocking socket):

f=Win32API.new(“ws2_32”, “ioctlsocket”, [“l”, “l”, “l”], ‘i’)
s=TCPServer.new(15000)
f.call(s.fileno, 2147772030, 1) #FIONBIO

This returns 10038, “Not a socket,” instead of 0, “Success.” s.fileno
is 3. On Windows, sockets are simply handles, which don’t need to be
low integers like 3, and usually aren’t.

What I need is to get the real handle to the socket. (Or any other way
to set a socket nonblocking in Windows.)

Also, a way to make TCPSocket.new not block would be nice. I’m trying
to make a chat program, and it needs to stay responsive, so it uses the
GUI toolkit’s functions to register a callback when the socket is
selected for.

Thanks,

···


Tom Felker

“Proprietary standard” is an oxymoron.

Hi,

On Windows, I do the following (trying to get a nonblocking socket):

f=Win32API.new(“ws2_32”, “ioctlsocket”, [“l”, “l”, “l”], ‘i’)
s=TCPServer.new(15000)
f.call(s.fileno, 2147772030, 1) #FIONBIO

Currently ruby’s on Windows (except for bccwin32 in 1.8) use
Winsock, and I don’t know whether Winsock and Winsock2 can
work each together.

This returns 10038, “Not a socket,” instead of 0, “Success.” s.fileno
is 3. On Windows, sockets are simply handles, which don’t need to be
low integers like 3, and usually aren’t.

What I need is to get the real handle to the socket. (Or any other way
to set a socket nonblocking in Windows.)

This might work for mingw32 and mswin32.

Win32API.new(“msvcrt”, “_get_osfhandle”, “I”, “I”).call(s.fileno)

Also, a way to make TCPSocket.new not block would be nice. I’m trying
to make a chat program, and it needs to stay responsive, so it uses the
GUI toolkit’s functions to register a callback when the socket is
selected for.

Note that non-blocking IO doesn’t work fine in 1.6, i.e.,
already recevied data will be lost at EAGAIN. This issue has
been fixed in 1.8.

···

At Wed, 19 Mar 2003 07:03:09 +0900, Tom Felker wrote:


Nobu Nakada

What I need is to get the real handle to the socket. (Or any other way
to set a socket nonblocking in Windows.)

There is an alternative way in Ruby: threads.

If you start a thread, and then read from a socket (say), it doesn’t matter
if it’s a “blocking” read; other threads can continue to run. The Ruby
interpreter hides all the details of how it achieves that.

Also, a way to make TCPSocket.new not block would be nice. I’m trying
to make a chat program, and it needs to stay responsive, so it uses the
GUI toolkit’s functions to register a callback when the socket is
selected for.

Threads sound like the right way for this. You may require a little care
with concurrency issues, but that’s all. At best: the chat receiver ‘owns’
one Window, and can put messages in their asynchronously. At worst: you need
a mutex so that only one thread is making a GUI API call at any time. It
depends on how thread-safe your GUI toolkit is.

You should certainly be able to get the responsiveness you’re after, and the
code will probably end up simpler.

Another approach (also based on threads) would be to have your message
receiver put whole received messages into a queue. It just needs to sit in a
loop of (read whole message - write it to queue). The queue add and remove
operations need to be thread-safe, but then your main loop can simply check
for whether there are messages in there or not, just as if it were doing a
non-blocking read, but without the complications of having to deal with a
read() which returns half a message.

Regards,

Brian.

···

On Wed, Mar 19, 2003 at 07:03:09AM +0900, Tom Felker wrote:

What I need is to get the real handle to the socket. (Or any other way
to set a socket nonblocking in Windows.)

There is an alternative way in Ruby: threads.

If you start a thread, and then read from a socket (say), it doesn’t matter
if it’s a “blocking” read; other threads can continue to run. The Ruby
interpreter hides all the details of how it achieves that.

Wow. My (flawed) understanding of how green threads work, in
combination with a misreading of the introduction to the Threads chapter
of the Programmer’s guide, made me ignore this. But after a quick test,
it works, even with GTK. Cool!

Also, a way to make TCPSocket.new not block would be nice. I’m trying
to make a chat program, and it needs to stay responsive, so it uses the
GUI toolkit’s functions to register a callback when the socket is
selected for.

Threads sound like the right way for this. You may require a little care
with concurrency issues, but that’s all. At best: the chat receiver ‘owns’
one Window, and can put messages in their asynchronously. At worst: you need
a mutex so that only one thread is making a GUI API call at any time. It
depends on how thread-safe your GUI toolkit is.

You should certainly be able to get the responsiveness you’re after, and the
code will probably end up simpler.

Another approach (also based on threads) would be to have your message
receiver put whole received messages into a queue. It just needs to sit in a
loop of (read whole message - write it to queue). The queue add and remove
operations need to be thread-safe, but then your main loop can simply check
for whether there are messages in there or not, just as if it were doing a
non-blocking read, but without the complications of having to deal with a
read() which returns half a message.

Using a queue and only one thread for the GUI sounds best, the only
question is how that thread gets out of Gtk.main when the queue is added
to. Using a timeout should work, but it’s hackish and a trade off
between CPU and latency.

Putting a mutex around all the API calls would be fine as long as it’s
OK to change widgets while the GUI thread is sleeping in Gtk.main,
because the mutex would have to be dropped when the GUI is asleep
there. I’m not sure (but maybe it is) if that’s safe in GTK. Gtk.main
still needs to be woken up eventually, because it only redraws the
screen in idle functions, which won’t be called again until a message is
received.

I eventually plan to write other UIs, in FOX, TK, or even text-based. I
think my design is flexible enough that this can be done in different
ways depending on the needs of the toolkit, with the network code
entirely platform-independent.

Regards,

Brian.

Thanks for removing my mental block about threads.

···

On Tue, 2003-03-18 at 16:58, Brian Candler wrote:

On Wed, Mar 19, 2003 at 07:03:09AM +0900, Tom Felker wrote:

Tom Felker

“Proprietary standard” is an oxymoron.