Base TCP server class. You must subclass GenericServer and provide a run method.
| [R] | config | The server configuration |
| [R] | listeners | Sockets listening for connections. |
| [R] | logger | The server logger. This is independent from the HTTP access log. |
| [R] | status | The server status. One of :Stop, :Running or :Shutdown |
| [R] | tokens | Tokens control the number of outstanding clients. The
|
Creates a new generic server from config. The default
configuration comes from default.
# File lib/webrick/server.rb, line 95 def initialize(config={}, default=Config::General) @config = default.dup.update(config) @status = :Stop @config[:Logger] ||= Log::new @logger = @config[:Logger] @tokens = SizedQueue.new(@config[:MaxClients]) @config[:MaxClients].times{ @tokens.push(nil) } webrickv = WEBrick::VERSION rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" @logger.info("WEBrick #{webrickv}") @logger.info("ruby #{rubyv}") @listeners = [] @shutdown_pipe = nil unless @config[:DoNotListen] if @config[:Listen] warn(":Listen option is deprecated; use GenericServer#listen") end listen(@config[:BindAddress], @config[:Port]) if @config[:Port] == 0 @config[:Port] = @listeners[0].addr[1] end end end
Retrieves key from the configuration
Adds listeners from address and port to the
server. See WEBrick::Utils.create_listeners
for details.
You must subclass GenericServer and implement #run which accepts a TCP client socket
Shuts down the server and all listening sockets. New listeners must be provided to restart the server.
Starts the server and runs the block for each connection.
This method does not return until the server is stopped from a signal
handler or another thread using stop or shutdown.
If the block raises a subclass of StandardError the exception is logged and ignored. If an IOError or Errno::EBADF exception is raised the exception is ignored. If an Exception subclass is raised the exception is logged and re-raised which stops the server.
To completely shut down a server call shutdown from ensure:
server = WEBrick::GenericServer.new
# or WEBrick::HTTPServer.new
begin
server.start
ensure
server.shutdown
end
# File lib/webrick/server.rb, line 158 def start(&block) raise ServerError, "already started." if @status != :Stop server_type = @config[:ServerType] || SimpleServer setup_shutdown_pipe server_type.start{ @logger.info "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" call_callback(:StartCallback) shutdown_pipe = @shutdown_pipe thgroup = ThreadGroup.new @status = :Running begin while @status == :Running begin sp = shutdown_pipe[0] if svrs = IO.select([sp, *@listeners], nil, nil, 2.0) if svrs[0].include? sp # swallow shutdown pipe buf = String.new nil while String === sp.read_nonblock([sp.nread, 8].max, buf, exception: false) break end svrs[0].each{|svr| @tokens.pop # blocks while no token is there. if sock = accept_client(svr) unless config[:DoNotReverseLookup].nil? sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup] end th = start_thread(sock, &block) th[:WEBrickThread] = true thgroup.add(th) else @tokens.push(nil) end } end rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex # if the listening socket was closed in GenericServer#shutdown, # IO::select raise it. rescue StandardError => ex msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}" @logger.error msg rescue Exception => ex @logger.fatal ex raise end end ensure cleanup_shutdown_pipe(shutdown_pipe) cleanup_listener @status = :Shutdown @logger.info "going to shutdown ..." thgroup.list.each{|th| th.join if th[:WEBrickThread] } call_callback(:StopCallback) @logger.info "#{self.class}#start done." @status = :Stop end } end