UPnP组播:M-SEARCH(发现)缺少答案

时间:2012-10-09 07:19:17

标签: c# windows upnp ssdp

我创建了一个小程序来测试UPnP Multicast(Visual C#2010 Express,在Windows 7 Professional 64 Bit上运行)。我可以从网络中的UPnP设备收到UPnP NOTIFY消息。但是当我发送M-SEARCH消息时,我没有得到任何答案。

我在iOS环境中测试了相同的代码(适用于iOS的Monotouch,在Mac上的iPhone模拟器上运行)。它运行良好,我得到了我的UPnP设备的所有搜索响应。我也可以从我的Windows程序中看到M-SEARCH消息。

看起来Windows(或防火墙?)隐藏了搜索响应。有什么想法吗?

以下是代码:

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 1900);
IPEndPoint MulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);

Socket UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.Bind(LocalEndPoint);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

Console.WriteLine("UDP-Socket setup done...\r\n");

string SearchString = "M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:3\r\n\r\n";

UdpSocket.SendTo(Encoding.UTF8.GetBytes(SearchString), SocketFlags.None, MulticastEndPoint);

Console.WriteLine("M-Search sent...\r\n");

byte[] ReceiveBuffer = new byte[64000];

int ReceivedBytes = 0;

while (true)
{
    if (UdpSocket.Available > 0)
    {
        ReceivedBytes = UdpSocket.Receive(ReceiveBuffer, SocketFlags.None);

        if (ReceivedBytes > 0)
        {
            Console.WriteLine(Encoding.UTF8.GetString(ReceiveBuffer, 0, ReceivedBytes));
        }
    }
}

3 个答案:

答案 0 :(得分:17)

是的,我解决了这个问题!小错误,影响很大:

我的程序在端口1900上发送M-SEARCH,该端口绑定到UPnP组播组。因为我将LocalEndPoint绑定到同一个端口,所以UPnP设备以单播方式应答到端口1900.在iOS上它起作用,因为我的程序是绑定到此端口的唯一服务。但在PC上,我发现有几个服务绑定到端口1900(找到“netstat -p UDP -a”)。因此,来自UPnP设备的单播消息被其他服务之一吸收。

解决方案:我将LocalEndPoint绑定到一个空闲端口(例如60000),现在它工作正常!

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);

答案 1 :(得分:5)

在创建本地端点时,使用端口0(零)绑定不使用固定端口的空闲端口。另一点发现了。绑定IPAddress.Any或IPAddress.Loopback从Microsoft(本地?)系统获取响应,其中绑定到其中一个LAN地址从本地网络获取响应。获取第一个IPV4地址可以这样做:

IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();

答案 2 :(得分:1)

对于后人:M-SEARCH不需要设置上述所有选项,甚至可能适得其反:

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

所以不要这样做。