I
Ivo Palli
Hi there,
I am making a multi-user, telnet based, bbs. At work I use Linux Ruby,
at home a Win32 port. (http://rubyinstaller.rubyforge.org/wiki/wiki.pl)
Now a multi-user server can be done in threads, but since I want to keep
it simple and avoid dead-locks and starvation problems, I decided not to
use threads. (I also read that threads can block the whole program if
they get stuck in system calls. That's not something I want.)
Instead I want to use a select, which is thankfully support in Ruby.
However a read to a socket which has data open always seems to block,
unless I specifically read what is available. Since I cannot know how
much data is waiting for me, I really need to do a non-blocking read. In
Linux it works, in Windows the fcntl call is not supported. As far as
I searched and tried, there is no other way to read data without blocking.
This guy
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3155
seems to have made a fix some time ago. Can I ask why it is not in the
standard distribution? On that note, can somebody point me to a binary
win32 distribution that _does_ have this patch incorporated?
One last thing. I ran the example below on both Linux and Win32.
Normally stdout buffering is done up until a '\n' after which output is
flushed (ANSI C, both on Linux and Win32). This behaviour is seen on the
Linux Ruby port, but not under Win32 where I had to put in
'STDOUT.sync=true'. Can this be considered a bug?
I'm using:
ruby 1.8.2 (2004-12-25) [i386-mswin32]
ruby 1.8.2 (2004-12-25) [i686-linux]
Server example, works on Linux, not on Win32:
# socket example - server side
# usage: ruby svr.rb
require "socket"
require "fcntl"
gs = TCPserver.open(0)
addr = gs.addr
addr.shift
printf("server is on %s\n", addr.join(":"))
socks = [gs]
loop do
nsock = select(socks);
next if nsock == nil
for s in nsock[0]
if s == gs
ns = s.accept
ns.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
socks.push(ns)
print(s, " is accepted\n")
else
if s.eof?
print(s, " is gone\n")
s.close
socks.delete(s)
else
print "[" + s.read + "]\n"
end
end
end
end
I am making a multi-user, telnet based, bbs. At work I use Linux Ruby,
at home a Win32 port. (http://rubyinstaller.rubyforge.org/wiki/wiki.pl)
Now a multi-user server can be done in threads, but since I want to keep
it simple and avoid dead-locks and starvation problems, I decided not to
use threads. (I also read that threads can block the whole program if
they get stuck in system calls. That's not something I want.)
Instead I want to use a select, which is thankfully support in Ruby.
However a read to a socket which has data open always seems to block,
unless I specifically read what is available. Since I cannot know how
much data is waiting for me, I really need to do a non-blocking read. In
Linux it works, in Windows the fcntl call is not supported. As far as
I searched and tried, there is no other way to read data without blocking.
This guy
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/3155
seems to have made a fix some time ago. Can I ask why it is not in the
standard distribution? On that note, can somebody point me to a binary
win32 distribution that _does_ have this patch incorporated?
One last thing. I ran the example below on both Linux and Win32.
Normally stdout buffering is done up until a '\n' after which output is
flushed (ANSI C, both on Linux and Win32). This behaviour is seen on the
Linux Ruby port, but not under Win32 where I had to put in
'STDOUT.sync=true'. Can this be considered a bug?
I'm using:
ruby 1.8.2 (2004-12-25) [i386-mswin32]
ruby 1.8.2 (2004-12-25) [i686-linux]
Server example, works on Linux, not on Win32:
# socket example - server side
# usage: ruby svr.rb
require "socket"
require "fcntl"
gs = TCPserver.open(0)
addr = gs.addr
addr.shift
printf("server is on %s\n", addr.join(":"))
socks = [gs]
loop do
nsock = select(socks);
next if nsock == nil
for s in nsock[0]
if s == gs
ns = s.accept
ns.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
socks.push(ns)
print(s, " is accepted\n")
else
if s.eof?
print(s, " is gone\n")
s.close
socks.delete(s)
else
print "[" + s.read + "]\n"
end
end
end
end