Skip to content

Instantly share code, notes, and snippets.

@reu
Created October 9, 2011 16:15
Show Gist options
  • Save reu/1273857 to your computer and use it in GitHub Desktop.
Save reu/1273857 to your computer and use it in GitHub Desktop.
LOL
# simple preforking echo server in Ruby
require "socket"
# Create a socket, bind it to localhost:2424, and start listening.
# Runs once in the parent. All forked children inherit the socket's
# file descriptor.
acceptor = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
address = Socket.pack_sockaddr_in(4242, "localhost")
acceptor.bind(address)
acceptor.listen(10)
# Close the socket when we exit the parent or any child process. This
# only closes the file descriptor in the calling process, it does not
# take the socket out of the listening state (until the last fd is
# closed).
#
# The trap is guaranteed to happen, and guaranteed to happen only
# once, right before the process exits for any reason (unless
# it's terminated with a SIGKILL).
trap("EXIT") { acceptor.close }
# Fork you some child processes. In the parent, the call to fork
# returns immediately with the pid of the child process. Fork never
# returns in the child because we exit at the end of the block.
3.times do
fork do
# now we're in the child process; trap (Ctrl-C) interrupts and
# exit immediately instead of dumping stack to stderr.
trap('INT') { exit }
puts "child #$$ accepting on shared socket (localhost:4242)"
loop do
# This is where the magic happens. accept(2) blocks until a
# new connection is ready to be dequeued.
puts "child #$$ waiting for message"
socket, address_info = acceptor.accept
message = socket.gets
message.match /GET \/(.+) /
filename = $1
puts "Trying to open file #{filename}"
if filename && File.exists?(filename)
file = File.read(filename)
response = "HTTP/1.1 200 OK\n"
response << "Content-Type: text/html;charset=utf-8\n"
response << "Contet-Length: #{file.size}\n"
response << file
else
response = "HTTP/1.1 404 NOT FOUND"
end
puts response
socket.write response
socket.close
end
exit
end
end
# Trap (Ctrl-C) interrupts, write a note, and exit immediately
# in parent. This trap is not inherited by the forks because it
# runs after forking has commenced.
trap("INT") { exit }
# Sit back and wait for all child processes to exit.
Process.waitall
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment