UPnP Multicast: отсутствующие ответы от M-SEARCH (Discovery)

Я создал небольшую программу для тестирования многоадресной рассылки UPnP (Visual С# 2010 Express, работающей под Windows 7 Professional 64 бит). Я могу получать сообщения UPnP NOTIFY от UPnP-устройств в своей сети. Но когда я отправляю сообщение M-SEARCH, у меня нет ответов.

Я тестировал один и тот же код в среде iOS (Monotouch для iOS, работающий на симуляторе iPhone на Mac). Там он работает нормально, и я получаю все поисковые ответы от своих устройств UPnP. Я также могу увидеть сообщение M-SEARCH из моей программы windows.

Похоже, что 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));
        }
    }
}

Ответ 1

Да, я решил проблему! Небольшая ошибка, большое влияние:

Моя программа отправляет M-SEARCH на порт 1900, который привязан к многоадресной группе UPnP. Поскольку я привязал LocalEndPoint к тому же порту, устройства UPnP отвечают одноадресной связью на порт 1900. На iOS это работало, потому что моя программа была единственной службой, связанной с этим портом. Но на ПК я нашел несколько сервисов, связанных с портом 1900 (найденный с помощью "netstat -p UDP -a" ). Таким образом, одноадресные сообщения с устройств UPnP были поглощены одной из других служб.

Решение: я привязал LocalEndPoint к свободному порту (например, 60000), и теперь он отлично работает!

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

Ответ 2

При создании локальной конечной точки используйте порт 0 (ноль), чтобы связать свободный порт, не используя фиксированный порт. Обнаружен еще один момент. Связывание IPAddress.Any или IPAddress.Loopback получает ответы от системы Microsoft (local?), Где привязка к одному из адресов локальной сети получает ответы от локальной сети. Получение первого IPV4-адреса можно сделать следующим образом:

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

Ответ 3

Для потомков: установка всех этих параметров выше не нужна для 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);

Так что не делай этого.