如何使用Ruby查找空闲的TCP服务器端口?

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

(It echoes standard input to the first connection and then dies.)
如何自动查找可用端口进行监听?
这似乎是在远程服务器上启动作业的唯一方法,然后通过唯一的作业ID回调。可以查询此作业ID以获取状态信息。为什么最初的设计者不能在调度作业时返回作业ID,我永远不会知道。单个端口无法使用,因为可能会发生多个回调的冲突;因此,端口仅用于约5秒钟。
6个回答

69

将0传递给端口号,这将导致系统从临时端口范围中为您选择一个端口。创建服务器后,可以请求其地址,其中包含服务器绑定的端口。

server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]

我正在使用基本的Socket(而不是TCPSocket),它没有addr方法。你知道我在这种情况下如何获取端口吗? - troelskn
3
回答我的问题,使用 socket.getsockname.unpack("snA*")[1]。 (该代码段是Python中的一行代码,用于获取套接字绑定的本地地址和端口号中的端口号。) - troelskn

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

这个实现(强调)了与问题中的代码片段相同的功能。


5
仅就小问题提出一点意见... 这样随机选择将会成为一个无限循环,理论上可能在服务器上运行未定义的时间,这种情况在已使用端口越多的情况下会变得更加糟糕。 - Nigel Thorne

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

这个池是线程安全的,它保证端口在被释放之前不会被其他线程或应用程序的其他地方使用。


0

也许你想测试某个端口是否正在监听,以下是我使用的方法:system('(6<>/dev/tcp/127.0.0.1/9292) &>/dev/null'),如果 9292 正在监听,则返回 true,否则返回 false。


-8

不要在随机端口上进行通信。选择一个默认端口并使其可配置。随机端口与防火墙不兼容。FTP就是这样做的,而且防火墙对它的支持非常困难 - 它必须深入检查数据包。


6
问题是如何找到可用的空闲端口,而不是是否使用随机端口是个好主意。 - ZombieDev
1
并非所有的TCP/IP流量都会经过防火墙。 - Roy Tinker

-9

我猜你可以按顺序尝试所有大于5000的端口。但是你如何向客户端程序通信你正在监听哪个端口呢?如果你需要在不同的环境中移动脚本,似乎更简单的方法是决定一个端口,然后使其易于配置。

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


请查看问题的最后一段(新添加的)。 - Marius Marais
2
这不应该是被接受的答案;请参见下面的https://dev59.com/J3VC5IYBdhLWcg3wtzyt#201528。 - Rob Howard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接