Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you find a free TCP server port using Ruby?

Tags:

http

ruby

sockets

I'm trying to create a use-once HTTP server to handle a single callback and need help with finding a free TCP port in Ruby.

This is the skeleton of what I'm doing:

require 'socket'
t = STDIN.read
port = 8081
while s = TCPServer.new('127.0.0.1', port).accept
  puts s.gets
  s.print "HTTP/1.1 200/OK\rContent-type: text/plain\r\n\r\n" + t
  s.close
  exit
end

(It echoes standard input to the first connection and then dies.)

How can I automatically find a free port to listen on?

This seems to be the only way to start a job on a remote server which then calls back with a unique job ID. This job ID can then be queried for status info. Why the original designers couldn't just return the job ID when scheduling the job I'll never know. A single port cannot be used because conflicts with multiple callbacks may occur; in this way the ports are only used for +- 5 seconds.

like image 758
Marius Marais Avatar asked Oct 14 '08 09:10

Marius Marais


2 Answers

Pass 0 in for the port number. This will cause the system to pick a port for you out of the ephemeral port range. Once you create the server, you can ask it for its addr, which will contain the port that the server is bound to.

server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
like image 159
Aaron Hinni Avatar answered Oct 02 '22 22:10

Aaron Hinni


It is actually quite easy when you don't try to do everything in one line :-/

require 'socket'
t = STDIN.read

port = 8080 # preferred port
begin
  server = TCPServer.new('127.0.0.1', port)    
rescue Errno::EADDRINUSE
  port = rand(65000 - 1024) + 1024
  retry
end

# Start remote process with the value of port

socket = server.accept
puts socket.gets
socket.print "HTTP/1.1 200/OK\rContent-type: text/plain\r\n\r\n" + t
socket.close

This accomplishes (strong word) the same as the snippet in the question.

like image 35
Marius Marais Avatar answered Oct 02 '22 22:10

Marius Marais