Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby,从UDP消息获取传入地址_Ruby_Sockets - Fatal编程技术网

Ruby,从UDP消息获取传入地址

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

我有一个绑定到系统上所有地址的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(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吗?警告:我不能真正正确地测试它,因为我只有一个可用的系统。这似乎是正确的,但我希望听到确认或分歧。