Multiple threads on single port

Hi all

Can I use Ruby threads to have more then 1 server process running on the
same port

something like

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
threads = []

10.times do |i|
threads[i] = Thread.new {
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end
}
end

Would this produce 10 processes that could take independent connection?

···

--
Posted via http://www.ruby-forum.com/.

Stuart Brand wrote:

Hi all

Can I use Ruby threads to have more then 1 server process running on the
same port

something like

[... example elided ...]

Not quite. I believe you can only have one thread listening to a port
at a given time. The idiom generally is to accept the connection in one
thread, and then pass the accepted connection to a different thread for
processing. So one thread handles accepting and multiple threads manage
the processing.

-- Jim Weirich

···

--
Posted via http://www.ruby-forum.com/\.

This will probably create multiple threads that accept connections. I only did
while(session = server.accept)
  Thread.new{...}
end
and it was in C. But you should be aware of the fact that depending on
the request processing you do in your thread you may not get any
thread switch until the request is handled. But at least print should
probably trigger the ruby thread scheduler.

HTH

Michal

···

On 6/6/06, Stuart Brand <stuart@server-solution.co.uk> wrote:

Hi all

Can I use Ruby threads to have more then 1 server process running on the
same port

something like

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
threads =

10.times do |i|
threads[i] = Thread.new {
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end
}
end

Would this produce 10 processes that could take independent connection?

Don't do this.

Just have a thread of execution that is in a while loop doing the accepts on
the socket, and have it spawn threads to handle the connections.

def handle_connection(session)
   puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end

while (session = server.accept)
  Thread.new {handle_connection(session)}
end

Kirk Haines

···

On Tuesday 06 June 2006 8:55 am, Stuart Brand wrote:

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
threads =

10.times do |i|
threads[i] = Thread.new {
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end
}
end

It works, but not terribly well. Whenever you call TCPServer#accept in a
program with more than one thread, the acceptor socket goes on a wait queue
inside Ruby until it's readable- it doesn't cross into the kernel. But I
tried your program and stress-tested it with ten threads, and performance
was abysmal. So I'd guess there's some interaction with Ruby's thread
scheduler that isn't quite normal. I'm not sure what you're trying to do but
you might be better off calling accept in one thread and passing the
accepted sockets to a thread pool, or using nonblocking IO. Another standard
alternative is to fork a process after accepting each socket- this is a
perfectly good solution if your performance needs are low.

···

On 6/6/06, Stuart Brand <stuart@server-solution.co.uk> wrote:

Hi all

Can I use Ruby threads to have more then 1 server process running on the
same port

something like

require 'socket'
port = (ARGV[0] || 80).to_i
server = TCPServer.new('localhost', port)
threads =

10.times do |i|
threads[i] = Thread.new {
while (session = server.accept)
  puts "Request: #{session.gets}"
  session.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n"
  session.print "<html><body><h1>#{Time.now}</h1></body></html>\r\n"
  session.close
end
}
end

Would this produce 10 processes that could take independent connection?

--
Posted via http://www.ruby-forum.com/\.

Ok, the final code for this example I have done is

require 'socket'
port = (ARGV[0] || 123).to_i
server = TCPServer.new('localhost', port)
threads = []

10.times do |i|
threads[i] = Thread.new {
        while (session = server.accept)
                puts "Request: #{session.gets}"
                session.print "HTTP/1.1 200/OK\r\nContent-type:
text/html\r\n\r\n"
                session.print
"<html><body><h1>#{Time.now}</h1></body></html>\r\n"
                session.close
        end
}
end

threads.each { |t| t.join}

However, the only stress I can do is the ab apache test, this shows the
same 1, 10 or 100 threads, how do I do a proper stress test??

Many thanks

Stuart

···

--
Posted via http://www.ruby-forum.com/.