如何使用Ruby找到一个免费的TCP服务器端口?
我正在尝试创建一个use once HTTP服务器来处理单个回调,并需要帮助在Ruby中找到一个免费的TCP端口 这是我正在做的工作的框架:如何使用Ruby找到一个免费的TCP服务器端口?,ruby,http,sockets,Ruby,Http,Sockets,我正在尝试创建一个use once 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.c
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秒。我想您可以按顺序尝试所有>5000的端口(例如)。但是,您将如何与客户端程序通信您正在侦听的端口?如果您需要在不同的环境之间移动脚本,那么确定端口并使其易于配置似乎更简单
对于HTTP,标准端口是80。我见过的可选端口有8080、880和8000。不要在随机端口上通信。选择一个默认值并使其可配置。随机端口与防火墙不兼容。FTP做到了这一点,而防火墙对它的支持是一场噩梦——它必须深入检查数据包。如果您不尝试在一行中完成所有操作,这实际上非常容易:-/
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
这与问题中的代码片段相同。为端口号传入0。这将导致系统为您选择临时端口范围之外的端口。创建服务器后,可以要求它提供其addr,该addr将包含服务器绑定到的端口
server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
也许你想测试一个端口是否正在监听,下面的内容对我有用
system('(6/dev/tcp/127.0.0.1/9292)和>/dev/null')
,如果9292正在侦听,则返回true,否则返回false。您可以尝试,一个简单的Ruby gem(我是作者):
不过,最好的办法是事后发布:
RandomPort::Pool::SINGLETON.new.acquire do |port|
# Use the port, it will be returned back
# to the pool afterward.
end
池是线程安全的,它保证端口在发布之前不会被其他线程或应用程序中的任何其他地方使用。请参阅问题的(新)最后一段。这不应该是公认的答案;请参见下文。我使用的是一个基本套接字(不是TCPSocket),它没有
addr
方法。您知道在这种情况下如何获取端口吗?回答我自己的问题,请使用socket.getsockname.unpack(“snA*”)[1]
来挑剔一下。。。像这样随机选取是一个无限循环,理论上可以在服务器上运行未定义的时间;使用的端口越多,情况就越糟。问题是如何找到可用端口,而不是使用随机端口是否是个好主意。并非所有TCP/IP流量都通过防火墙。
RandomPort::Pool::SINGLETON.new.acquire do |port|
# Use the port, it will be returned back
# to the pool afterward.
end