Warum UDP-socket abonnierten multicast-Gruppe nimmt eine nicht-multicast-Meldung?
Überblick: ich habe ein server und ein client, wo beide versuchen Entdeckung der jeweils anderen über UDP. Wenn der server startet, es sendet eine multicast-Nachricht (239.1.1.1), dass es lebendig ist. Wenn der client startet, sendet er eine multicast-Nachricht (239.1.1.2), dass es lebendig ist. Beide server-und client-Abonnement zum jeweils anderen multicast-Nachrichten zu empfangen, deren Getriebe. Auf diese Weise, unabhängig davon, welche Anwendung (server oder client) startet erste, der eine oder andere wird über Ihre Existenz.
Auf der client-Seite habe ich das folgende tun:
- Einrichten einer socket zu abonnieren und zu empfangen, server entstanden multicast-Nachrichten.
- Einrichten eines Empfangs-socket zum empfangen von server-Antworten auf Kunden-multicast
Nachricht pro #3 unten. - Senden Sie eine muticast-Nachricht (für server zu empfangen und darauf zu reagieren), dass der client ausgeführt wird.
- Erhalten server-Antwort an clients multicast-Nachricht gesendet, in der #3.
Frage: Alles funktioniert gut, außer, dass Sie sowohl empfangen Steckdosen am Ende immer der server (nicht multicast) - Antwort an den client. Ich bin nicht klar, ob dies ist das erwartete Verhalten oder nicht. Kann ich die beiden empfangen Steckdosen, die auf einer? #1 abonniert ist auf dem server die multicast-und die #2 ist einfach nur Zuhören für eine direkte übertragung vom server auf den gleichen port (nicht-multicast message from server). Kann ich sicher entfernen Sie die zweite empfangende socket?
Siehe Quelltext unten (ich entfernt die Ausnahmebehandlung für eine vereinfachte code-Darstellung).
Client-code:
//1. Set up a socket and asynchronously listen for server startup multicasts.
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
listenSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, 1);
listenSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
listenSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse("239.1.1.1")));
EndPoint clientEndPoint = new IPEndPoint(0, 0);
listenSocket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length,
SocketFlags.None, ref clientEndPoint,
new AsyncCallback(OnServerMessageReceived), (object)this);
//2. Set up socket to receive the server's response to client's multicast.
Socket receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
receiveSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, 1);
receiveSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
receiveSocket.ReceiveTimeout = 3000; //Timeout after 3 seconds.
//3. Send a multicast message for server to respond to.
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
EndPoint multicastEndPoint = new IPEndPoint(IPAddress.Parse("239.1.1.2"), 50000);
sendSocket.SendTo(packet, packet.Length, SocketFlags.None, multicastEndPoint);
//4. Wait for server to respond to the multicast message (timeout = 3 seconds).
byte[] receiveBuff = new byte[2048];
EndPoint serverEndPoint = new IPEndPoint(0, 0);
int bytesRead = receiveSocket.ReceiveFrom(receiveBuff, ref serverEndPoint);
Server-code:
//Receive multicast message sent from client (in asynchronous callback method).
EndPoint clientEndPoint = new IPEndPoint(0, 0);
int bytesRead = listenSocket.EndReceiveFrom(asyncResult, ref clientEndPoint);
//Send response back to the client (change port to 50000).
EndPoint destination = new IPEndPoint((clientEndPoint as IPEndPoint).Address,
50000);
Socket responseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
responseSocket.SendTo(response, response.Length, SocketFlags.None, destination);
- In einer multicast-Umgebung warum die server selbst müssen sich bewusst sein, die client(s)?
- Der einzige Grund, ich bin per multicast an alle zu etablieren Entdeckung zwischen allen clients und einem server. Sobald die discovery abgeschlossen ist, schalte ich um auf TCP/IP (WCF netTcpBinding), wo der server kann dann das senden von Nachrichten an clients. Die clients können auch senden Sie die server-Benachrichtigungen über bestimmte client-side-events.
- Sie haben erwähnt, dass verschiedene (multicast ) - client-Adresse. Sagen Sie, dass client 1 eine Adresse und client 2 wird einen anderen?
- Wenn Sie mit multicast discovery-warum nicht mit WCF discovery? es scheint viel einfacher, und es scheint, dass, was Sie brauchen: msdn.microsoft.com/en-us/library/dd456791(v=vs. 110).aspx
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Antwort auf deine Frage ist "ja, dies ist das erwartete Verhalten". Sie brauchen nicht zu öffnen Sie eine separate Buchse zum empfangen von unicast-Paketen auf dem gleichen port.
PS
Es scheint wie overkill haben Ihre Server beitreten zu einer multicast-Gruppe zu hören, für neue Kunden - Sie könnte einfach die Server regelmäßig übermitteln, die ein Leuchtfeuer für die client-multicast-Adresse, die sagen "ich bin hier" (sagen wir, einmal alle 30 Sekunden).
Erhalten sockets binden an eine Adresse, das heißt, Sie erhalten unicast -, broadcast-und multicast-Datenverkehr. Sie können binden an eine Schnittstelle-Adresse nur unicast-Verkehr, und Sie können binden nur an die multicast-Gruppe zu erhalten nur multicast-Datenverkehr.
Beim senden eines UDP-datagram können Sie die Ziel-Adresse, die möglicherweise multicast oder unicast. Sie können sich daher reduzieren sich die server-und client-code, um jeweils ein sockel.
Während ich bin nicht sicher, ob es auf Ihre Frage, ich würde erwarten, dass beide client-und server-to-talk auf der gleichen IP-multicast-Adresse (z.B. 239.1.1.1). Im moment sieht es aus wie die, die Sie gegeben haben der client und der server eine Adresse jedes einzelnen, und was passiert, wenn/wenn Sie die Einführung einer neuen client ?
Bessere option wäre die Verwendung einer service-discovery-Protokoll, wie Bonjour oder Avahi als Ihre eigenen Rollen, denn Sie haben viele Probleme gelöst bereits.