Обнаружение SSDP в Windows 8 Metro не надежно

У меня проблемы с реализацией обнаружения SSDP в программе Windows 8 Metro. Ниже приведен код:

public async Task SearchForDevices()
    {
        var socket = new DatagramSocket();
        socket.MessageReceived += async (sender, args) =>
                                            {
                                                Debug.WriteLine("Received data" + DateTime.Now);
                                                DataReader reader = args.GetDataReader();

                                                uint count = reader.UnconsumedBufferLength;
                                                string data = reader.ReadString(count);
                                                Debug.WriteLine(data);
                                                var response = new Dictionary<string, string>();
                                                foreach (
                                                    string x in
                                                        data.Split(new[] {"\r\n", "\n"}, StringSplitOptions.None))
                                                {
                                                    if (x.Contains(":"))
                                                    {
                                                        string[] strings = x.Split(':');
                                                        response.Add(strings[0].ToLower(), x.Remove(0, strings[0].Length + 1));
                                                    }
                                                }

                                                Device device = await GetXml(response);
                                                Debug.WriteLine("Device found");
                                                if (DeviceFound != null)
                                                    DeviceFound(this, new DeviceFoundEventArgs(device));
                                            };
        await socket.BindEndpointAsync(null, "");
        HostName hostName = new HostName("239.255.255.250");
        socket.JoinMulticastGroup(hostName);

        string message = "M-SEARCH * HTTP/1.1\r\n" +
                               "HOST: " + hostName.DisplayName + ":1900\r\n" +
                               "ST: upnp:rootdevice\r\n" +
                               "MAN: \"ssdp:discover\"\r\n" +
                               "MX: 3\r\n\r\n";

        DateTime start = DateTime.Now;
        TimeSpan interval = new TimeSpan(0, 0, 30);
        Debug.WriteLine(start);
        IOutputStream stream = await socket.GetOutputStreamAsync(hostName, "1900");
        var writer = new DataWriter(stream) { UnicodeEncoding = UnicodeEncoding.Utf8 };
        writer.WriteString(message);
        await writer.StoreAsync();
        await Task.Delay(1500);
    }

Этот код не является надежным на всех. примерно 50% раз он не может найти подключенное устройство, в то время как другие обнаруживают могут найти. Но иногда это работает.

Мой сетевой анализатор (SmartSniff) иногда не может даже перехватить его запрос SSDP, хотя я звонил много раз.

Я не думаю, что это асинхронная проблема, поскольку она иногда срабатывает. Пожалуйста, помогите мне! Спасибо!

3 ответа

Попробуйте связать локальную конечную точку с IP-адресом, назначенным локальному сетевому адаптеру, на который вы хотите отправить многоадресный запрос UDP.

Тот факт, что вы не видите исходящий пакет UDP с вашим анализатором пакетов, заставляет меня поверить, что запрос отправляется через сетевой интерфейс, отличный от того, который вы захватываете. Я предполагаю, что у вас есть несколько сетевых интерфейсов (например, Ethernet и WLAN). При работе с многоадресной рассылкой необходимо убедиться, что ваши запросы отправляются на все сетевые интерфейсы, чтобы физически достичь всех подключенных сетей.

Смотрите также Запрос локального IP-адреса.

Если я правильно догадываюсь, что await Task.Delay(1500); означает, что вы позволили заданию запустить 1.5secs до завершения, тогда у вас была интересная причина проблемы.

Видите ли, "MX: 3" в M-SEARCH означает "ответить со случайной задержкой до 3 секунд". Учитывая, что вы ждете только 1,5 секунды, имеет смысл, что примерно 50% ответов потеряно для вас;-)

Я думаю, что вам придется заставить SocketOptionName.ReuseAddress на вашем сокете. Я не могу объяснить, почему я так думаю, вы явно не совершаете ту же ошибку, что и @Joern, пытаясь использовать порт 1900 для локальной конечной точки. Но это единственное различие, которое я вижу, и его ситуация по-прежнему применима: вполне вероятно, что на вашем компьютере с Windows уже работает другая контрольная точка UPnP. Попробуйте отключить службу UPnP в инструментах администрирования Windows и посмотрите, работает ли ваш код более надежно.

Или попробуйте переписать установление сокета UDP способом @ Joern. Я не гуру C#, но всегда подозрительно, когда определенные API позволяют вам делать одно и то же разными способами.

Другие вопросы по тегам