UPnP Multicast: пропущенные ответы от M-SEARCH (Discovery)
Я создал небольшую программу для тестирования многоадресной рассылки UPnP (Visual C# 2010 Express, работающей в 64-разрядной версии Windows 7 Professional). Я могу получать сообщения 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));
}
}
}
3 ответа
Да, я решил проблему! Маленькая ошибка, большое влияние:
Моя программа отправляет M-SEARCH через порт 1900, который связан с многоадресной группой UPnP. Поскольку я привязал LocalEndPoint к тому же порту, устройства UPnP отвечают одноадресной рассылкой на порт 1900. На iOS это работало, потому что моя программа была единственной службой, связанной с этим портом. Но на ПК я обнаружил несколько служб, связанных с портом 1900 (с помощью "netstat -p UDP -a"). Таким образом, одноадресные сообщения от устройств UPnP были поглощены одной из других служб.
Решение: я привязал LocalEndPoint к свободному порту (например, 60000), и теперь он работает отлично!
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);
При создании локальной конечной точки используйте порт 0 (ноль) для привязки свободного порта, не использующего фиксированный порт. Еще одна точка обнаружена. Привязка IPAddress.Any или IPAddress.Loopback получают ответы от системы Microsoft (локальная?), Где в качестве привязки к одному из адресов локальной сети получают ответы из локальной сети. Получить первый адрес IPV4 можно следующим образом:
IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();
Для потомков: установка всех этих опций выше не нужна для 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);
Так что не делай этого.