2008-10-16 5 views
12

Der Client verbindet sich über GenuineChannels mit dem Server (wir erwägen den Wechsel zu DotNetRemoting). Mit find möchte ich die IP- und Port-Nummer eines Servers ermitteln, mit dem eine Verbindung hergestellt werden soll.Was ist der beste Weg für eine Client-App, einen Server in einem lokalen Netzwerk in C# zu finden?

Es scheint wie eine Brute-Force-Ansatz wäre versuchen, jede IP im Netzwerk versuchen Sie die aktiven Ports (nicht einmal sicher, ob das möglich ist), aber es muss einen besseren Weg geben.

+0

Re: Brute-Force-Ansatz - Es ist möglich. Sie wollen ** einen besseren Weg. :) Selbst mit einem massiv parallelen Ansatz mit mehreren Sockeln (konzeptionell ähnlich wie fping) kann es immer noch einige Minuten dauern, alle Knoten (und alle möglichen Ports) in einem LAN-Subnetz zu testen. Ich habe Code im Produkt, das genau das tut, weil es keine bessere Wahl für diesen Dienst gab. Seufzer. –

Antwort

11

Erwägen Sie, ein bestimmtes UDP-Paket zu senden. Wenn der oder die Server das gesendete UDP-Paket sehen, senden sie eine Antwort. Der Client kann die Antworten von allen Servern sammeln und mit ihnen oder basierend auf einem Wahlalgorithmus eine Verbindung herstellen.

Siehe Beispiel für Client (ungetesteten Code):


using System.Net; 
using System.Net.Sockets; 

[STAThread] 
static void Main(string[] args) 
{ 
    Socket socket = new Socket(AddressFamily.InterNetwork, 
    SocketType.Dgram, ProtocolType.Udp); 
    socket.Bind(new IPEndPoint(IPAddress.Any, 8002)); 
    socket.Connect(new IPEndPoint(IPAddress.Broadcast, 8001)); 
    socket.Send(System.Text.ASCIIEncoding.ASCII.GetBytes("hello")); 

    int availableBytes = socket.Available; 
    if (availableBytes > 0) 
    { 
     byte[] buffer = new byte[availableBytes]; 
     socket.Receive(buffer, 0, availableBytes, SocketFlags.None); 
     // buffer has the information on how to connect to the server 
    } 
} 
1

Lassen Sie den Server an einem bestimmten Port im Netzwerk auf Broadcast warten (UDP verwenden). Wenn der Client gestartet wird, sendet er eine "Ping" -Anfrage an diesen Port. Wenn der Server einen "Ping" sieht, sendet er eine Nachricht mit der TCP-Adresse und dem Port, die für die Verbindung des Clients erforderlich sind.

+0

Während die Implementierung Ihres eigenen UDP-Port-Kanals für einen "Ping" und "Reply" einfach, schnell und scheinbar schmerzlos ist, kommt es zu der Port/Use-Verwirrung, wenn Sie nicht durch den Standard-Veröffentlichungsprozess gehen (auch ein Schmerz) . Außerdem gibt es bereits viele Discovery-Protokolle mit Implementierungen auf den meisten Betriebssystemen. Denken Sie daran: "Ein guter Programmierer schreibt guten Code. Ein großer Programmierer verwendet bereits vorhandenen guten Code." –

8

Ich würde sagen, der beste Weg, Bonjour/Zeroconf/mDNS für C# zu verwenden ist; Es wurde viel darüber nachgedacht, wie man mit dem Netzwerk gut spielen kann. IE es Pings weniger häufig im Laufe der Zeit, wenn möglich, usw. Es gibt Mono.Zeroconf, und ich lese, es ist ein älteres .NET-Projekt in der Apple SDK, aber ich habe es nicht gefunden.

So wäre die einfachste Bonjour for Windows zu installieren, erhalten dann die Windows Binaries for Mono.Zeroconf versuchen das Beispiel die Mono.Zeroconf.dll fallen MZClient.exe und/oder Mono.Zeroconf.Providers.Bonjour.dll in Ihre Projektreferenzen und gehen.

Etwas wie folgt aus:

var service = new Mono.Zeroconf.RegisterService { 
       Name = "Use Me for Stuff", 
       RegType = "_daap._tcp", 
       ReplyDomain = "local.", 
       Port = 0024200, 
       TxtRecord = new Mono.Zeroconf.TxtRecord { 
          {"I have no idea what's going on", "true"}} 
       }; 
service.Register(); 

var browser = new Mono.Zeroconf.ServiceBrowser(); 
browser.ServiceAdded += 
    delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) { 
     Console.WriteLine("Found Service: {0}", args.Service.Name); 
     args.Service.Resolved += 
      delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) { 
       var s = args.Service; 
       Console.WriteLine(
        "Resolved Service: {0} - {1}:{2} ({3} TXT record entries)", 
        s.FullName, s.HostEntry.AddressList[0], s.Port, s.TxtRecord.Count); 
      }; 
     args.Service.Resolve(); 
    }; 
browser.Browse("_daap._tcp", "local"); 
2

WS-Discovery ist ein Protokoll für diesen Zweck bestimmt sind. Es hat ein paar verschiedene Variationen, verschiedene Arten von Rundfunk und Proxies. http://en.wikipedia.org/wiki/WS-Discovery

.NET WCF4 implementiert dies.

+0

WS-Discovery eignet sich gut zum Entdecken von "Web Services". Diese dienen in der Regel SOAP oder REST. Ein anderer Stilserver passt möglicherweise besser zu einer anderen Stilerkennung. –

4

Ich wollte nur auf ein alternatives Zeroconf NuGet-Paket hinweisen: Zeroconf. Es hat keine nativen Abhängigkeiten, so dass Sie Bonjour für Windows oder etwas anderes nicht installieren müssen.

Es hat Unterstützung für .NET 4.5, WP8 und Win8.

+3

Gute Netiquette würde einen Disclaimer enthalten, dass dies Ihr eigenes Projekt ist, für das Sie werben. Ich werde es nicht kennzeichnen, weil es immer noch relevant ist, aber etwas zu beachten. – nathanchere

+1

Nicht sicher, warum dies wichtig ist, da es sich um eine kostenlose Open Source-Lösung handelt, die eine bessere und einfachere technische Implementierung bietet. Jeder, der zur Nuget-Seite oder zur GitHub-Projektseite geht, sieht, dass ich es bin. Es gibt keinen Grund, etwas abzulehnen. Hier wird kein "Produkt" oder Geld gemacht. –

+0

Wäre nett, wenn es auch Server-Modus zum Verifizieren hätte. Wo ist diese "bessere und einfachere technische Umsetzung"? – kchoi

Verwandte Themen