3

C#を使用して、 Windows ストアアプリケーション用の基本的なSSDP ( UDP ) ブロードキャスト/リスナーを実装しようとしています。

UDPネットワーキングに使用する必要があるクラスがWindows.Networking.Sockets含まれていることがわかりました。DatagramSocket

ただし、現在の試行は問題なく実行されているようですが、Wireshark経由で結果が得られず、ネットワーク上のデバイスから応答が返されません。

私が現在使用している (そして RT シミュレーターで実行している) コードは次のとおりです。

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 秒のタイムアウトを使用しています。

4

2 に答える 2

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;
}
于 2013-01-11T22:32:58.927 に答える
1

一致する仕様:

HTTP 拡張フレームワークで必要な MAN。NTS および ST フィールド値とは異なり、MAN ヘッダー フィールドのフィールド値は二重引用符で囲まれています。拡張機能のスコープ (名前空間) を定義します。「ssdp:discover」でなければなりません。

次に、あなたのコード

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

でなければなりません

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

この助けを願っています。

于 2013-02-15T07:59:34.977 に答える