【发布时间】: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