2008-10-16 6 views
12

Le client se connecte au serveur à l'aide de GenuineChannels (nous envisageons de passer à DotNetRemoting). Ce que je veux dire par trouver est d'obtenir l'adresse IP et le numéro de port d'un serveur auquel se connecter.Quelle est la meilleure façon pour une application cliente de trouver un serveur sur un réseau local en C#?

Il semble que l'approche de la force brute serait d'essayer tous les IP sur le réseau essayer les ports actifs (même pas si c'est possible), mais il doit y avoir une meilleure façon.

+0

re: approche par force brute - C'est possible. Vous voulez ** vouloir ** un meilleur moyen. :) Même en utilisant une approche de socket multiple massivement parallèle (conceptuellement similaire à fping), il peut encore prendre plusieurs minutes pour tester tous les nœuds (et tous les ports potentiels) dans un sous-réseau LAN. J'ai du code dans le produit qui fait exactement cela parce qu'il n'y avait pas de meilleur choix pour ce service. Soupir. –

Répondre

11

Envisagez de diffuser un paquet UDP spécifique. Lorsque le serveur ou les serveurs voient le paquet UDP diffusé, ils envoient une réponse. Le client peut collecter les réponses de tous les serveurs et commencer à s'y connecter ou à partir d'un algorithme d'élection.

Voir par exemple pour le client (de code non testé):


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

Demandez au serveur d'écouter la diffusion sur un port spécifique du réseau (doit utiliser UDP). Lorsque le client commence à diffuser une requête ping sur ce port. Lorsque le serveur voit un "ping", il renvoie un message avec l'adresse TCP et le port requis pour que le client s'y connecte.

+0

Bien que l'implémentation de votre propre canal de port UDP pour un "ping" et une "réponse" soit facile, rapide et semble indolore, cela ajoute à la confusion port/utilisation si vous ne passez pas par le processus de publication des normes. . En outre, il existe déjà de nombreux protocoles de découverte avec des implémentations sur la plupart des systèmes d'exploitation. Rappelez-vous: "Un bon programmeur écrit du bon code, un bon programmeur réutilise le bon code préexistant." –

8

je dirais que la meilleure façon est d'utiliser Bonjour/Zeroconf/mDNS pour C#; il y a eu beaucoup de réflexion pour que ça fonctionne bien avec le réseau; IE il pings moins souvent au fil du temps si possible, etc. Il ya Mono.Zeroconf, et j'ai lu il y a un projet .NET plus ancien dans le Apple SDK mais je ne l'ai pas trouvé.

Ainsi, le plus simple serait d'installer Bonjour for Windows, puis obtenir le Windows Binaries for Mono.Zeroconf essayer l'exemple MZClient.exe laisser tomber le Mono.Zeroconf.dll et/ou Mono.Zeroconf.Providers.Bonjour.dll dans vos références de projet et aller.

Quelque chose comme ceci:

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 est un protocole prévu à cet effet. Il a quelques variations différentes, différentes saveurs de diffusion et de proxies. http://en.wikipedia.org/wiki/WS-Discovery

.NET WCF4 l'implémente.

+0

WS-Discovery se prête bien à la découverte de "Web Services". Ceux-ci servent typiquement SOAP ou REST. Un serveur de style différent peut mieux s'adapter à une découverte de style différente. –

4

Je voulais juste signaler un autre paquet Zeroconf NuGet: Zeroconf. Il ne possède aucune dépendance native, vous n'avez donc pas besoin d'installer Bonjour pour Windows ou quoi que ce soit d'autre.

Il prend en charge .NET 4.5, WP8 et Win8.

+3

Une bonne nétiquette inclurait un avertissement que c'est votre propre projet que vous faites de la publicité. Ne pas le signaler parce que c'est toujours pertinent, mais quelque chose à considérer. – nathanchere

+1

Je ne sais pas pourquoi cela est important car il s'agit d'une solution gratuite et open source qui permet une implémentation technique plus simple et plus simple. Quiconque se rend sur la page Nuget ou sur le site du projet GitHub verrait que c'est moi; il n'y a aucune raison de rejeter quoi que ce soit. Il n'y a pas de «produit» ou d'argent réalisé ici. –

+0

Serait bien s'il avait le mode serveur aussi pour vérifier. Où est cette «mise en œuvre technique meilleure et plus simple»? – kchoi

Questions connexes