From: Gregory Millam Date: 2004-03-20T04:34:54+09:00 Subject: Re: Server on Ruby Received: Sat, 20 Mar 2004 04:06:50 +0900 And lo, Alexandr wrote: > So, I have a simply echo socket server on Perl: > > --------------------------------------------------------------------------------------------------------------- > #!/usr/bin/perl -wT > require 5.002; > use strict; > use IO::Socket; > use IO::Select; > > # create a socket to listen to a port > my $listen = IO::Socket::INET->new(Proto => 'tcp', > LocalPort => 2324, > Listen => 1, > Reuse => 1) or die $!; > > # to start with, $select contains only the socket we're > listening on > my $select = IO::Select->new($listen); > > my @ready; > > # wait until there's something to do > while(@ready = $select->can_read) { > > my $socket; > > # handle each socket that's ready > for $socket (@ready) { > > # if the listening socket is ready, accept a new > connection > if($socket == $listen) { > my $new = $listen->accept; > $select->add($new); > print $new->fileno . ": connected\n"; > } else { > > # otherwise, read a line of text and send it back > again > my $line=""; > $socket->recv($line,80); > $line ne "" and $socket->send($line) or do { > > # either can't send or can't receive, so they must have > hung up > print $socket->fileno . ": disconnected\n"; > $select->remove($socket); > $socket->close; > }; > } > } > } If you're insistent on needint select() functionality, use IO::select(readarray,[writearray, [errorarray, [timeout]]]) For your purpose, I'd use something like this: --------------------- PORT=2324 require 'socket' require 'thread' # A function called for each socket def handle_incoming(sock) # Threads are easy - lets put each incoming socket in # Its own thread. =). Thread.new { # Socket.addr -> [networkdomain, port, name, ip] puts "New connection from #{sock.addr[2]} (#{sock.addr[3]})" # Echo each line we get back to the socket. # When the socket gets an error or is closed, # gets returns nil, so the while loop exits. while (line = sock.gets) sock.puts line end puts "Connection from #{sock.addr[2]} closed." } end # Create a new listener that listens on all addresses # and the port number in constant PORT (defined above) # TCPServer.new(local_address,port) listener = TCPServer.new('',PORT) # listener.accept returns sockets of new connections. # This while loop calls handle_incoming on each new # socket created. Doing it this way instead of putting # the Thread.new { ... } code inside this while loop # bypasses ickiness with local variables being shared. while (new_socket = listener.accept) handle_incoming(new_socket) end ---------------------- It runs each socket in its own Ruby thread (Not to be confused with system threads), and network threads do not hang the interpreter when there are other threads to run. Hope that helps. - Greg Millam