2012-02-23 31 views
4

マルチキャストメッセージを送信し、メッセージが送信されたアドレスに応答が送信されるのを待つ次のコードがあります。 Wiresharkのトラフィックを見ると、メッセージが正常に送信され、応答が正しいIPとポートに戻ってきますが、ソケットが受信ラインから返ってくることはありません。応答が取得されていないようです。メッセージを送信して同じソケットで応答を受信する方法

var multicastAddress = IPAddress.Parse("239.255.255.250"); 
    var multicastPort = 1900; 
    var unicastPort = 1901;   

    using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) 
    { 
     socket.Bind(new IPEndPoint(IPAddress.Any, unicastPort)); 
     socket.Connect(new IPEndPoint(multicastAddress, multicastPort)); 
     var thd = new Thread(() => 
      { 
       try 
       { 
        while (true) 
        { 
         var response = new byte[8000]; 
         EndPoint ep = new IPEndPoint(IPAddress.Any, unicastPort); 
         socket.ReceiveFrom(response, ref ep); 
         var str = Encoding.UTF8.GetString(response); 
         Devices.Add(new SsdpDevice() {Location = str}); 
        } 
       } 
       catch 
       { 
        //TODO handle exception for when connection closes 
       } 
      }); 
     socket.Send(broadcastMessage, 0, broadcastMessage.Length, SocketFlags.None); 
     thd.Start(); 
     Thread.Sleep(30000); 
     socket.Close(); 
    } 

私は、ソケットクラスの非同期メソッドを使用する必要があります知っているとのThread.sleepに頼る停止必要がありますが、私はちょうど私がコードを片付ける前に、簡単な例作業を取得したいです。

+0

あなたの空の漁獲量は、実際にエラーをキャッチしていますか? – Smudge202

+0

接続が閉じられ、応答を待っているときにSocketExceptionがスローされます。 – Gavin

答えて

9

ギャビン、これをチェックアウト:

  • は異なるポートを使用しないでください。あなたはどのようにしてマルチキャストし、別のもので受信すると思いますか?
  • Connect()を使用しないでください。マルチキャストは(ブロードキャストと同様に)コネクションレス型のメッセージングです。
  • Bind()の後にマルチキャストにソケットオプションを設定します。
  • Send()の代わりにSendTo()を使用してください。この場合は動作しません。
  • 最初に受信を開始します(ブロッキングモードであっても、別のエンドポイントです)。次に送信します。

、簡単な作業例:

var broadcastMessage = Encoding.UTF8.GetBytes("Hello multicast!"); 
var multicastAddress = IPAddress.Parse("239.255.255.250"); 
var signal = new ManualResetEvent(false); 
var multicastPort = 1900; 

using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) 
{ 
    var multicastEp = new IPEndPoint(multicastAddress, multicastPort); 
    EndPoint localEp = new IPEndPoint(IPAddress.Any, multicastPort); 

    // Might want to set this: 
    //socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); 
    socket.Bind(localEp); 
    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, IPAddress.Any)); 
    // May want to set this: 
    //socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 0); // only LAN 
    var thd = new Thread(() => 
     { 
      var response = new byte[8000]; 
      socket.ReceiveFrom(response, ref localEp); 
      var str = Encoding.UTF8.GetString(response).TrimEnd('\0'); 
      Console.WriteLine("[RECV] {0}", str); 
      signal.Set(); 
      Console.WriteLine("Receiver terminating..."); 
     }); 
    signal.Reset(); 
    thd.Start(); 

    socket.SendTo(broadcastMessage, 0, broadcastMessage.Length, SocketFlags.None, multicastEp); 
    Console.WriteLine("[SEND] {0}", Encoding.UTF8.GetString(broadcastMessage)); 
    signal.WaitOne(); 
    Console.WriteLine("Multicaster terminating..."); 
    socket.Close(); 
    Console.WriteLine("Press any key."); 
    Console.ReadKey(); 
} 
+0

UDPのNoDelayオプションはどのように機能しますか?私はNagleのTCPアルゴリズムを無効にすることは知っていますが、UDPソケットのためのNagleのアルゴリズムはそれではないと思います。 –

+1

削除されました。それを指摘してくれてありがとう。実際にはNoDelayはTCPだけです。当時の私は確信が持てませんでした。そのため、あなたは「あなたが使いたいかもしれない」と書いています。問題は、もしあなたがgoogleにそれを書くと、人々がUDP + NoDelayを使って書いたたくさんのコードがあるということです。これは私の答えに含めたのですが、私はそれを詳しく見ていないので、コメントアウトしました。 –

+0

ああ、良いよ。世界はまだ私には意味があります:)。もう1つ質問です。ネットワークデバイスはTTLが0のパケットを転送しませんか?これは、TTLを0に設定することは、最初のネットワークデバイスがあなたのパケットを受信し破棄するだけなので、意味がないことを意味します。 –

関連する問題