2013-01-11 2 views
3

Я пытаюсь реализовать основную SSDP (UDP) широковещательного/слушателя для Windows Store приложения с помощью C#.SSDP (UDP) в приложениях Windows Store (.NET)

Я обнаружил, что Windows.Networking.Sockets содержит DatagramSocket класса, который является то, что мне нужно использовать для UDP сетей.

Однако мои текущие попытки, похоже, выполняются просто отлично, но не имеют результатов через Wireshark и не получают ответа от устройств в сети.

Вот код, я в настоящее время использую (и работает через RT Simulator):

public async static Task<IEnumerable<HueBridge>> DiscoverAsync(TimeSpan timeout) 
{ 
    if (timeout <= TimeSpan.Zero) 
    throw new ArgumentException("Timeout value must be greater than zero.", "timeout"); 

    var discoveredBridges = new List<HueBridge>(); 

    using (var socket = new DatagramSocket()) 
    { 
    while (true) 
    { 
     var bridgeWasFound = false; 

     socket.MessageReceived += (sender, e) => 
     { 
     var bpx = true; // breakpoint here for success 
     }; 

     var multicastIP = new HostName("239.255.255.250"); 
     await socket.BindServiceNameAsync("1900"); 
     socket.JoinMulticastGroup(multicastIP); 

     using (var writer = new DataWriter(socket.OutputStream)) 
     { 
     var request = new StringBuilder(); 
     request.AppendLine("M-SEARCH * HTTP/1.1"); 
     request.AppendLine("HOST: 239.255.255.250:1900"); 
     request.AppendLine("MAN: ssdp:discover"); 
     request.AppendLine("MX: 5"); 
     request.AppendLine("ST: ssdp:all"); 

     writer.WriteString(request.ToString()); 
     await writer.FlushAsync(); 
     } 

     if (timeout > TimeSpan.Zero) 
     await Task.Delay(timeout); 

     if (!bridgeWasFound) 
     break; // breakpoint here for failure check 
    } 
    } 

    return discoveredBridges; 
} 

Любые идеи о том, что я могу делать неправильно? Я не получаю исключения, и у меня есть надлежащие Возможности, установленные в манифесте. Моя точка останова на break всегда получает удар, и я использую таймаут 10 секунд.

ответ

3

Кажется, я нашел проблему (и).

Во-первых, я должен использовать socket.BindEndpointAsync(null, string.Empty) вместо socket.BindServiceNameAsync("1900"), который будет правильно прослушивать широковещательные пакеты.

Во-вторых, writer.FlushAsync() не записывается в розетку; однако writer.StoreAsync() ...

Вот конечный результат, который не работает (почти):

public async static Task<IEnumerable<HueBridge>> DiscoverAsync(TimeSpan timeout) 
{ 
    if (timeout <= TimeSpan.Zero) 
    throw new ArgumentException("Timeout value must be greater than zero.", "timeout"); 

    var discoveredBridges = new List<HueBridge>(); 
    var multicastIP = new HostName("239.255.255.250"); 
    var bridgeWasFound = false; 

    using (var socket = new DatagramSocket()) 
    { 
    socket.MessageReceived += (sender, e) => 
    { 
     var reader = e.GetDataReader(); 
     var bytesRemaining = reader.UnconsumedBufferLength; 
     var receivedString = reader.ReadString(bytesRemaining); 

     // TODO: Check for existing bridges, only add new ones to prevent infinite loop. 
     // TODO: Create new bridge and add to the list. 

     bridgeWasFound = true; 
    }; 

    await socket.BindEndpointAsync(null, string.Empty); 
    socket.JoinMulticastGroup(multicastIP); 

    while (true) 
    { 
     bridgeWasFound = false; 

     using (var stream = await socket.GetOutputStreamAsync(multicastIP, "1900")) 
     using (var writer = new DataWriter(stream)) 
     { 
     var request = new StringBuilder(); 
     request.AppendLine("M-SEARCH * HTTP/1.1"); 
     request.AppendLine("HOST: 239.255.255.250:1900"); 
     request.AppendLine("MAN: ssdp:discover"); 
     request.AppendLine("MX: 3"); 
     request.AppendLine("ST: ssdp:all"); 

     writer.WriteString(request.ToString()); 
     await writer.StoreAsync(); 

     if (timeout > TimeSpan.Zero) 
      await Task.Delay(timeout); 

     if (!bridgeWasFound) 
      break; 
     } 
    } 
    } 

    return discoveredBridges; 
} 
1

Согласно Спецификации:

MAN ТРЕБУЕТСЯ по HTTP Framework Extension. В отличие от значений NTS и ST значение поля поля заголовка MAN заключено в двойные кавычки ; он определяет область (пространство имен) расширения. ДОЛЖНО быть «ssdp: открыть».

, то ваш код

request.AppendLine("MAN: ssdp:discover"); 

должен быть

request.AppendLine("MAN: \"ssdp:discover\""); 

Надеется, что это поможет.

Смежные вопросы