15

我正在尝试创建一个一次性 HTTP 服务器来处理单个回调,并且需要帮助以在 Ruby 中找到一个免费的 TCP 端口。

这是我正在做的事情的骨架:

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

(它将标准输入回显到第一个连接,然后死掉。)

我怎样才能自动找到一个空闲端口来监听?

这似乎是在远程服务器上启动作业的唯一方法,然后使用唯一的作业 ID 进行回调。然后可以查询此作业 ID 以获取状态信息。为什么最初的设计师在安排工作时不能只返回工作 ID,我永远不会知道。不能使用单个端口,因为可能会与多个回调发生冲突;这样,端口仅使用 +- 5 秒。

4

6 回答 6

70

输入 0 作为端口号。这将导致系统从临时端口范围中为您选择一个端口。创建服务器后,您可以向它询问其地址,该地址将包含服务器绑定到的端口。

server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
于 2008-10-14T15:00:57.977 回答
3

当您不尝试在一行中完成所有操作时,这实际上很容易:-/

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

这完成(强词)与问题中的片段相同。

于 2008-10-14T11:34:40.047 回答
1

你可以试试random-port,一个简单的 Ruby gem(我是作者):

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

不过,最好的方法是在之后发布它:

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

该池是线程安全的,它保证该端口不会被另一个线程或应用程序中的任何其他地方使用,直到它被释放。

于 2018-10-04T06:48:59.763 回答
0

也许您想测试一个端口正在监听的天气,以下对我 system('(6<>/dev/tcp/127.0.0.1/9292) &>/dev/null')有用,如果 9292 正在监听,则返回 true,否则返回 false。

于 2018-08-09T13:47:15.243 回答
-8

不要在随机端口上通信。选择一个默认值并使其可配置。随机端口与防火墙不兼容。FTP 做到了这一点,而防火墙对它的支持是一场噩梦——它必须深入检查数据包。

于 2008-10-14T10:01:26.770 回答
-9

我想你可以依次尝试所有 > 5000 的端口(例如)。但是您将如何与客户端程序通信您正在侦听的端口?如果您需要在不同环境之间移动脚本,那么决定端口并使其易于配置似乎更简单。

对于 HTTP,标准端口是 80。我见过使用的替代端口是 8080、880 和 8000。

于 2008-10-14T09:32:23.130 回答