Как найти свободный порт TCP-сервера с использованием Ruby? - PullRequest
10 голосов
/ 14 октября 2008

Я пытаюсь создать одноразовый HTTP-сервер для обработки одного обратного вызова и мне нужна помощь в поиске свободного порта TCP в Ruby.

Это скелет того, что я делаю:

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

(повторяет стандартный ввод для первого соединения и затем умирает.)

Как я могу автоматически найти свободный порт для прослушивания?

Это, кажется, единственный способ запустить задание на удаленном сервере, который затем перезванивает с уникальным идентификатором задания. Этот идентификатор задания может быть запрошен для получения информации о состоянии. Почему оригинальные дизайнеры не могли просто вернуть идентификатор работы при планировании работы, я никогда не узнаю. Один порт не может быть использован, потому что могут возникнуть конфликты с несколькими обратными вызовами; таким образом, порты используются только в течение + - 5 секунд.

Ответы [ 6 ]

65 голосов
/ 14 октября 2008

Введите 0 для номера порта. Это заставит систему выбрать порт за пределами диапазона эфемерного порта. Создав сервер, вы можете запросить его адрес, который будет содержать порт, к которому привязан сервер.

server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
3 голосов
/ 14 октября 2008

На самом деле это довольно легко, когда вы не пытаетесь сделать все в одной строке: - /

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

Это выполняет (сильное слово) то же, что и фрагмент в вопросе.

1 голос
/ 04 октября 2018

Вы можете попробовать random-port , простой Ruby gem (я автор):

require 'random-port'
port = RandomPort::Pool.new.aquire

Лучший способ, однако, выпустить его потом:

RandomPort::Pool::SINGLETON.new.acquire do |port|
  # Use the port, it will be returned back
  # to the pool afterward.
end

Пул является поточно-ориентированным и гарантирует, что порт не будет использоваться другим потоком или где-либо еще в приложении, пока он не будет освобожден.

0 голосов
/ 09 августа 2018

Может быть, вы хотите проверить погоду, один порт слушает, у меня работает следующее system('(6<>/dev/tcp/127.0.0.1/9292) &>/dev/null'), вернуть true, если 9292 слушает, в противном случае вернуть false.

0 голосов
/ 14 октября 2008

Не общаться на случайных портах. Выберите вариант по умолчанию и сделайте его настраиваемым. Случайные порты несовместимы с брандмауэрами. FTP делает это, и поддержка брандмауэра - это кошмар - он должен глубоко проверять пакеты.

0 голосов
/ 14 октября 2008

Я думаю, вы можете попробовать все порты> 5000 (например) в последовательности. Но как вы будете сообщать клиентской программе, какой порт вы слушаете? Кажется, проще выбрать порт, а затем сделать его легко настраиваемым, если вам нужно переместить сценарий между различными средами.

Для HTTP стандартным портом является 80. Я видел альтернативные порты 8080, 880 и 8000.

...