【问题标题】:Multicast packet seen in Wireshark, but not received by user program (Windows and Linux)在 Wireshark 中看到多播数据包,但用户程序未收到(Windows 和 Linux)
【发布时间】:2017-04-10 22:13:54
【问题描述】:

我正在尝试使用来自 Ruby 程序的多播检测网络连接设备。我从官方检测程序中嗅探了网络流量,发现计算机向225.0.0.37:12345发送了一个数据包,设备在225.0.0.38:12346上响应。该设备连接到由 Netgear 交换机、Windows 计算机和 Linux 计算机组成的本地网络。我已经让我的程序发送一个与官方程序相同的数据包。

我的问题是我的程序和官方检测程序都没有收到响应。使用 Wireshark,我可以清楚地看到设备没有失败地响应,并且数据包清楚地到达了我运行 Wireshark 的 Linux 计算机,但是在 Windows 计算机上运行的官方程序和我在 Linux 计算机上运行的我自己的 Ruby 程序都没有得到回应。

我的两台电脑都有两个网络适配器,一个连接到同一个本地交换机,一个连接到另一个交换机,然后连接到一个可以访问互联网的大型 LAN。我试过在电脑之间使用不同品牌的开关,但没有任何区别。

我在 Internet 上进行了广泛搜索,但没有找到任何可以解决我的问题的方法。我很感激能得到任何帮助。

这里是用tcpdump捕获的相关数据包,第一个是我的程序发送的,第二个是设备的响应:

13:30:25.773019 IP 192.168.0.1.12345 > 225.0.0.37.12345: UDP, length 15
13:30:25.773770 IP 192.168.0.125.39129 > 225.0.0.38.12346: UDP, length 228

这是我程序中的(简化的)sn-p:

MULTICAST_SEND_ADDRESS = '225.0.0.37'
MULTICAST_SEND_PORT = 12345
MULTICAST_RESPONSE_ADDRESS = '225.0.0.38'
MULTICAST_RESPONSE_PORT = 12346
BIND_ADDRESS = '0.0.0.0'

# Transmit packet on all adapters - this part works fine
packet = [ID_STRING].pack("Z*")
addresses = Socket.ip_address_list
addresses.each do |addr|
    next unless addr.pfamily == Socket::PF_INET
    socket = UDPSocket.new
    socket.bind(addr.ip_address, MULTICAST_SEND_PORT)
    socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
    socket.send(packet, 0, MULTICAST_SEND_ADDRESS, MULTICAST_SEND_PORT)
    socket.close
end

# Receive packet - this should work, but doesn't
membership = IPAddr.new(MULTICAST_SEND_ADDRESS).hton + IPAddr.new(BIND_ADDRESS).hton
listen_socket = UDPSocket.new
listen_socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, membership)
listen_socket.bind(BIND_ADDRESS, MULTICAST_RESPONSE_PORT)
packet, addr = listen_socket.recvfrom(1024)
# We never get to this line since there's nothing received
puts packet

【问题讨论】:

  • 您的计算机上有订阅多播地址的进程吗?许多交换机会进行 IGMP 侦听,并且它们不会将多播传送到主机未订阅多播组的接口。还有一个已知的 IGMP 侦听问题,两台交换机没有 mrouter。
  • 不,没有正在运行的服务监听该端口或地址。由于 Linux 机器上的 Wireshark/tcpdump 看到了包,所以它必须由交换机传送到接口。主网络当然有一个路由器,而连接设备的小型网络只有一个交换机。 IGMP 窥探问题究竟适用于什么场景,它需要什么?
  • 多播不同于普通的单播网络。希望接收多播的进程必须通过发送 IGMP 消息来订阅多播组,请求将到该组的流量发送给它。交换机过去只是以广播的方式向每个接口发送多播。 IGMP 侦听已更改,因此交换机仅将多播发送到主机已发送 IGMP 加入的接口。交换机之间不发送 IGMP,因此您需要一个 mrouter 或 IGMP 查询器。请参阅this question 和答案。
  • 我想我明白了,但如果是这样的话,Wireshark 应该不会收到数据包。另外,我忘了提到的是我的程序通过多播检测其他设备没有问题。
  • 255.255.255.255 地址是有限广播地址,而不是多播地址。广播被传送到每个交换机接口。

标签: ruby linux networking multicast


【解决方案1】:

我最终发现了问题所在。尽管我看到的所有代码示例都说了什么,但似乎您无法绑定到地址“0.0.0.0”以获取多宿主计算机上的所有接口。我不知道这是否曾经有效并且已经改变,或者我发现的所有示例都只在单宿主机器上进行了测试,但是当我将套接字绑定到正确接口的实际 ip 时,它开始工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    相关资源
    最近更新 更多