【问题标题】:How can you specify a source address in a multicast join in Haskell?如何在 Haskell 的多播连接中指定源地址?
【发布时间】:2014-09-30 18:29:03
【问题描述】:

在网络多播 Haskell 文档中,我看到了一个函数

setInterface :: Socket -> HostName -> IO ()
Set the outgoing interface address of the multicast.

如何使用它在多播连接中指定源地址?以下代码在运行时会产生给定的输出..(为保护隐私而屏蔽 IP 地址)

代码

import Network.BSD
import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import Network.Multicast hiding (multicastReceiver)
import Text.Printf
import Data.ByteString as B hiding (putStrLn)

sourceIP = "192.168.MMM.NNN"
mcastIP = "224.0.XXX.YYY"
mcastPort = 32101

mcastLoop :: Socket -> IO ()
mcastLoop sock = do
    (msg, addr) <- recvFrom sock 1024
    printf "%s-> %s\n" (show addr) (show . B.unpack $ msg)
    mcastLoop sock 

multicastReceiver :: HostName -> PortNumber -> IO Socket
multicastReceiver host port = do
    proto <- getProtocolNumber "udp"
    sock  <- socket AF_INET Datagram proto
    setInterface sock sourceIP

{-# LINE 81 "src/Network/Multicast.hsc" #-}
    setInterface sock sourceIP
    bindSocket sock $ SockAddrInet port 0
    setInterface sock sourceIP
{-# LINE 82 "src/Network/Multicast.hsc" #-}
    setInterface sock sourceIP
    addMembership sock host
    return sock

main :: IO ()
main = withSocketsDo $ do
    sock <- multicastReceiver mcastIP mcastPort
    dropMembership sock mcastIP
    setInterface sock sourceIP
    addMembership sock mcastIP
    mcastLoop sock

输出

~ - sudo tcpdump -n -nn -i any "host 224.0.XXX.YYY"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
08:00:44.463153 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:00:52.498722 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:00:58.301711 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:01:08.408710 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:02:04.104707 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:03:08.545718 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:04:02.634709 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:05:03.757718 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:06:10.600716 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:07:07.248707 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:08:10.202708 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY
08:09:02.390708 IP 10.52.ZZZ.WWW > 224.0.XXX.YYY: igmp v2 report 224.0.XXX.YYY

这是运行的 C++/Haskell 应用程序的比较(根据 EJP 的要求)

~/sandbox - sudo tcpdump -i any "host 192.168.MMM.NNN"        
[sudo] password for gresko: 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes

# C++ application started
16:15:55.490156 IP 192.168.MMM.NNN > 224.0.62.108: igmp v2 report 224.0.62.108
# C++ application killed
16:16:04.689342 IP 192.168.MMM.NNN > all-routers.mcast.net: igmp leave 224.0.62.108

# Haskell application started
# Haskell application killed

【问题讨论】:

  • 这个问题类似,但没有回答我的问题:stackoverflow.com/questions/6111204/…
  • 你能详细说明“不起作用”吗?与您所看到的相比,您期望的行为是什么?
  • 阐述了预期的行为
  • 您需要在加入群组之前调用setInterface。在 Haskell 中如何做到这一点是另一个问题。也许 dropMembership/addInterface/addMembership。看起来他们给我设计了错误的构造函数。
  • @EJP:我就是这么想的。我还尝试复制 multicastReceiver 的源并在创建套接字后立即插入 setInterface 调用。那也没用..

标签: haskell networking multicast


【解决方案1】:

Haskell 作者在他们的构造函数中不允许这样做。它根本不应该带组参数,因为它不允许您在加入组之前设置多播接口。或者,该组应该是可选的。

我还要说他们应该提供一个addMembership() 覆盖或替代方案,它需要一个 NIC 地址和一个组地址。底层的 Sockets 系统调用毕竟支持它。

然而,除非Haskell的setInterface()方法根本不起作用,在这种情况下你无能为力,

dropMembership()
setInterface()
addMembership()

应该可以。

在我断定 setInterface() 不起作用之前,我想确认您确实没有看到任何 IGMP 消息从该接口发出。

我怀疑真正发生的事情是发件人没有正确发送。

【讨论】:

  • 好主意。我已将提示的高潮合并到原始帖子中的一个代码/输出示例中。看看,让我知道你的想法。编辑:注意,这很有趣,因为在setInterface 中设置无效的源 ip(即计算机中任何接口不拥有的 IP)会产生错误。所以看起来它实际上在做某事
  • -i any 表示在所有接口上嗅探,"host x.y.z.w" 表示捕获进出指定主机的流量。来自 C++ 的等效捕获显示出站数据包具有“192.168.MMM.NNN”作为其源 IP。此外,如果“会员报告”不是联接,那是什么?
猜你喜欢
  • 1970-01-01
  • 2011-08-31
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 2011-08-27
  • 2013-05-14
相关资源
最近更新 更多