gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 16:01:36 24 4
gpt4 key购买 nike

我有一个绑定(bind)到系统上所有地址的 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

这将产生如下内容:

data: ["test message\n", #<Addrinfo: 172.16.5.110:41949 UDP>]

我是否可以设置套接字选项或其他选项来返回本地 IP?

请注意,这也需要适用于 IPv6。提前致谢,戴夫。

最佳答案

UNIX Network Programming关于这个主题有这样的话:

With a UDP socket, however, the destination IP address can only be obtained by setting the IP_RECVDSTADDR socket option for IPv4 or the IPV6_PKTINFO socket option for IPv6 and then calling recvmsg instead of recvfrom.

Ruby 的套接字库有 recvmsg这比底层 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 套接字选项,我认为它可能已经取代了 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 还提供了一个 Socket.udp_server_loop method , 这会产生消息和 UDPSource对象到您提供的 block ,并且此源对象有一个 local_address 字段。 Looking at the source这似乎像我上面所做的那样检查 PKTINFO 数据以获取 IPv6 请求的目标地址,但不是 IPv4。此方法分别绑定(bind)到所有可用的 IP 地址,并且仅使用 IP4 请求的传入接口(interface)地址,这对于 weak end system model 可能不准确。 .但是,使用 Socket.udp_server_loop 可能更简单。

关于Ruby,从UDP消息中获取传入地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23819812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com