Ruby,从UDP消息获取传入地址
我有一个绑定到系统上所有地址的UDP服务器,我想知道消息的ip地址。有什么办法吗 下面是我的示例代码:Ruby,从UDP消息获取传入地址,ruby,sockets,Ruby,Sockets,我有一个绑定到系统上所有地址的UDP服务器,我想知道消息的ip地址。有什么办法吗 下面是我的示例代码: sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0) sock.bind(Addrinfo.udp('', 2400)) while(true) sockset = IO.select([sock]) sockset[0].each do |sock| data = sock.recvfrom(102
sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
sock.bind(Addrinfo.udp('', 2400))
while(true)
sockset = IO.select([sock])
sockset[0].each do |sock|
data = sock.recvfrom(1024)
puts "data: " + data.inspect
end
end
sock.close
这将产生如下结果:
数据:[“测试消息\n”,#]
我是否可以设置套接字选项或其他东西来返回本地IP
请注意,这也需要适用于IPv6。提前谢谢你,戴夫。关于这个主题,我想说:
但是,对于UDP套接字,只能通过为IPv4设置IP\u RECVDSTADDR
socket选项或为IPV6设置IPV6\u PKTINFO
socket选项,然后调用recvmsg
而不是recvfrom
来获取目标IP地址
Ruby的socket库提供了一个比底层C函数更容易使用的函数,但是仍然需要一些工作来获取所需的信息。目标IP地址包含在从recvmsg
返回的辅助数据数组中。以下是您的代码版本,它适合于使用recvmsg
并获取IPv4的目标地址:
require 'socket'
require 'ipaddr'
sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
# Set the required socket option:
sock.setsockopt :IPPROTO_IP, :IP_RECVDSTADDR, true
sock.bind(Addrinfo.udp('0.0.0.0', 2400))
while(true)
sockset = IO.select([sock])
sockset[0].each do |sock|
mesg, sender, _, *anc_data = sock.recvmsg
# Find the relevant data and extract it into a string
dest = IPAddr.ntop(anc_data.find {|d| d.cmsg_is?(:IP, :RECVDSTADDR)}.data)
puts "Data: #{mesg}, Sender: #{sender.ip_address}, Destination: #{dest}"
end
end
这是IPv6的一个版本。还有一个RECVPKTINFO
socket选项,我认为它可能已经取代了PKTINFO
——根据您的系统,您可能需要使用它
require 'socket'
sock = Socket.new(Socket::AF_INET6, Socket::SOCK_DGRAM, 0)
# Set the socket option for IP6:
sock.setsockopt :IPPROTO_IPV6, :IPV6_PKTINFO, true
sock.bind(Addrinfo.udp('0::0', 2400))
while(true)
sockset = IO.select([sock])
sockset[0].each do |sock|
mesg, sender, _, *anc_data = sock.recvmsg
# Find and extract the destination address
dest = anc_data.find {|d| d.cmsg_is?(:IPV6, :PKTINFO)}.ipv6_pktinfo_addr
puts "Data: #{mesg}, Sender: #{sender.ip_address}, Destination: #{dest.ip_address}"
end
end
Ruby还提供了一个,它为您提供的块生成消息和对象,这个源对象有一个local\u address
字段。这似乎像我上面所做的那样检查PKTINFO
数据,以获取IPv6请求的目标地址,但不用于IPv4。此方法单独绑定到所有可用的IP地址,并仅将传入接口的地址用于IP4请求,这对于特定的应用程序可能不准确。但是,使用Socket.udp\u server\u loop
可能会更简单,但是172.16.5.110
在您的示例中不是本地IP吗?警告:我不能真正正确地测试它,因为我只有一个可用的系统。这似乎是正确的,但我希望听到确认或分歧。