【问题标题】:Send an UDP multicast packet on all my IPs在我所有的 IP 上发送一个 UDP 多播数据包
【发布时间】:2013-03-06 15:23:43
【问题描述】:

我正在尝试在我的所有网络接口(2 个 LAN,一个 wifi)上发送一个多播数据包。我最初关注了这个tutorial

我遇到的问题是,数据包似乎只有我的一个 IP 地址。

这是我当前的代码。

private static void SendOnAllCards(int port, String address)
{
    using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
    {
        mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                                    new MulticastOption(IPAddress.Parse(address)));
        mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
        mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
        IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(address), port);
        mSendSocket.Connect(ipep);


        byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
        mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
    }
}

我尝试手动操作:

private static void SendOnAllCards(int port, string remoteAddressSrc)
{
    foreach (IPAddress remoteAddress in Dns.GetHostAddresses(Dns.GetHostName()).Where(i=>i.AddressFamily == AddressFamily.InterNetwork))
    {

        using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
        {
            mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                                        new MulticastOption(IPAddress.Parse(remoteAddressSrc)));
            mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
            mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
            IPEndPoint ipep = new IPEndPoint(remoteAddress, port);
            mSendSocket.Connect(ipep);


            byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
            mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
        }
    }
}

这可行,但这意味着我必须创建与我的 IP 一样多的套接字(在此示例中,我在每次发送时创建它们,但这只是一个测试),而且我不喜欢我的方式获取我所有的 IP。

那么正确的做法是什么?

编辑第二个额外问题:为什么当我在 Connect 中指定本地 ip(指定远程地址,但在 Bind 上没有)时这有效?

【问题讨论】:

    标签: c# sockets network-programming udp multicast


    【解决方案1】:

    似乎我们必须在网络接口上进行迭代,在本地 IP 上进行绑定并执行 Send*To* 调用:

    public void SendTestMessage()
    {
        foreach (IPAddress localIp in
            Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
        {
            IPAddress ipToUse = localIp;
            using (var mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                                            new MulticastOption(_multicastIp, localIp));
                mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
                mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                mSendSocket.MulticastLoopback = true;
                mSendSocket.Bind(new IPEndPoint(ipToUse, _port));
    
    
                byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
                var ipep = new IPEndPoint(_multicastIp, _port);
                mSendSocket.SendTo(bytes, ipep);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用 WMI 类 Win32_NetworkAdapter 找到网络适配器。您可能需要优化查询实例带来的结果,因为 Windows 和第三方软件都创建了许多“虚拟适配器”。 我编写了一个快速的豪华脚本来使用 WMI 检索适配器。这应该只显示具有 IP 地址的适配器。这只是为了显示您可以查询以检索激活适配器的 WMI 信息。

      $networkadapters = @(Get-CimInstance -ClassName Win32_NetworkAdapter -Property *)
      $networkadapters_configs = @($networkadapters | Get-CimAssociatedInstance -ResultClassName Win32_NetworkAdapterConfiguration)
      
      0..($networkadapters.Length-1) | %{
          if($networkadapters_configs[$_].IPAddress -gt '') {
              Write-Output "Adapter #$($_)" 
              Write-Output $networkadapters[$_]
              Write-Output "Config #$($_)" 
              Write-Output $networkadapters_configs[$_]
          }
      }
      

      【讨论】:

      • 我不确定它对我有什么帮助?
      • 然后您可以使用分配给每个网卡的 IP 信息来广播您的多播消息。在您的原始帖子中,您正在迭代分配给主机的 IP 地址,但每个 NIC 可以有多个 IP 地址。这是使用 WMI 提取网络适配器 IP 绑定的示例,然后可用于准确发送这些消息。
      • 我的问题不是寻找网络接口,而是如何通过socket向多个接口发送数据
      • 通过查找多播并将其发送到分配给网络接口的唯一 IP 地址,您可以将数据包发送到每个可能的多播组。每个网卡可以有多个 ip,每个 IP 可以属于不同的多播组,或者它们可能都属于一个。如果要向每个可能的多播组发送多播,则需要迭代 IP 并将其发送到每个组。
      • 啊,我意识到您的示例代码中根本不是joining any multicast group。我相信这是你的主要问题。您仍然可以拥有单独的多播组(例如,来自 vpn 连接),但大多数情况下,在套接字绑定之前加入。下面是一些显示发送多播消息的相关源代码,包括配置套接字:multicastdotnet
      猜你喜欢
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多