views:

55

answers:

2

I'm trying to run a mock webserver within a thread within a class. I've tried passing the class' @server property to the thread block but as soon as I try to do server.accept the thread stops. Is there some way to make this work? I want to basically be able to run a webserver off of this script while still taking user input via stdin.gets. Is this possible?

class Server
    def initialize()
        @server = TCPServer.new(8080)
    end
    def run()
        @thread = Thread.new(@server) { |server|
            while true
                newsock = server.accept
                puts "some stuff after accept!"
                next if !newsock
                # some other stuff
            end
        }
    end
end
def processCommand()
    # some user commands here
end
test = Server.new
while true do
  processCommand(STDIN.gets)
end

In the above sample, the thread dies on server.accept

A: 

In the code you posted, you're not calling Server#run. That's probably just an oversight in making the post. Server.accept is supposed to block a thread, returning only when someone has connected.

Anyone who goes into writing an HTTP server with bright eyes soon learns that it's more fun to let someone else do that work. For quick and dirty HTTP servers, I've got good results enlisting the aid of WEBrick. It's a part of the Ruby library. Here's a WEBrick server that will serve up "Boo!" When you connect your browser to localhost:8080/:

#!/usr/bin/ruby1.8

require 'webrick'

class MiniServer

  def initialize
    Thread.new do
      Thread::abort_on_exception = true
        server = WEBrick::HTTPServer.new(:BindAddress=>'127.0.0.1',
                                         :Port=>8080,
                                         :Logger=>WEBrick::Log.new('/dev/stdout'))
        server.mount('/', Servlet, self)
        server.start
    end
  end

  private

  class Servlet < WEBrick::HTTPServlet::AbstractServlet

    def initialize(webrick_server, mini_server)
    end

    def do_GET(req, resp)
      resp.body = "<html><head></head><body>Boo!</body></html>"
    end
    alias :do_POST :do_GET

  end

end

server = MiniServer.new
gets
Wayne Conrad
I've got it working now but now the problem is that I have to pass it one line of input at the command prompt for it to send the socket whatever output is queued up while it's waiting for me to provide the input.
bob c
@bob c, That's important info. You might want to add it to the question.
Wayne Conrad
A: 

I don't know ruby, but it looks like server.accept is blocking until you get a tcp connection... your thread will continue as soon as a connection is accepted.

You should start the server in your main thread and then spawn a new thread for each connection that you accept, that way your server will immediately go to accept another connection and your thread will service the one that was just accepted.

Lirik