2008-10-16 8 views
12

El cliente se conecta al servidor utilizando GenuineChannels (estamos considerando cambiar a DotNetRemoting). Lo que quiero decir con find es obtener el IP y el número de puerto de un servidor para conectarse.¿Cuál es la mejor forma de que una aplicación cliente encuentre un servidor en una red local en C#?

Parece que un enfoque de fuerza bruta sería intentar cada IP en la red probar los puertos activos (ni siquiera estoy seguro si eso es posible) pero debe haber una mejor manera.

+0

re: enfoque de fuerza bruta - Es posible. Usted ** quiere ** una mejor manera. :) Incluso utilizando un enfoque de socket múltiple masivamente paralelo (conceptualmente similar a fping) todavía puede tomar varios minutos probar todos los nodos (y todos los puertos potenciales) en una subred de LAN. Tengo un código en el producto que hace exactamente eso porque no había mejor opción para ese servicio. Suspiro. –

Respuesta

11

Considere la posibilidad de transmitir un paquete UDP específico. Cuando el servidor o los servidores ven el paquete UDP emitido, envían una respuesta. El cliente puede recopilar las respuestas de todos los servidores y comenzar a conectarse a ellas o basándose en un algoritmo de elección.

Ver el ejemplo del cliente (código no probado):


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

Solicite al servidor que escuche la transmisión en un puerto específico de la red (debe usar UDP), cuando el cliente comienza ha emitir una solicitud de "ping" en ese puerto. cuando el servidor ve un "ping" envía de vuelta un mensaje con la dirección TCP y el puerto requerido para que el cliente se conecte.

+0

Si bien implementar su propio canal de puerto UDP para un "ping" y "respuesta" es fácil, rápido y parece sencillo, agrega confusión al puerto/uso si no pasa por el proceso de publicación de estándares (también un problema) . Además, ya hay muchos protocolos de descubrimiento disponibles con implementaciones en la mayoría de los sistemas operativos. Recuerde: "Un buen programador escribe un buen código. Un gran programador reutiliza un código bueno preexistente". –

8

yo diría que la mejor manera es utilizar Bonjour/Zeroconf/mDNS para C#; se pensó mucho en hacerlo jugar bien con la red; Es decir, suena con menos frecuencia con el tiempo si es posible, etc. Hay Mono.Zeroconf, y he leído que hay un proyecto .NET más antiguo en el Apple SDK pero no lo he encontrado.

lo tanto el más fácil sería instalar Bonjour for Windows, a continuación, obtener la Windows Binaries for Mono.Zeroconf probar el ejemplo MZClient.exe caer el Mono.Zeroconf.dll y/o Mono.Zeroconf.Providers.Bonjour.dll en las referencias del proyecto y listo.

Algo como esto:

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 es un protocolo diseñado para este propósito. Tiene algunas variaciones diferentes, diferentes sabores de difusión y proxies. http://en.wikipedia.org/wiki/WS-Discovery

.NET WCF4 implementa esto.

+0

WS-Discovery se presta bien para descubrir "Servicios web". Estos típicamente sirven SOAP o REST. Un servidor de estilo diferente puede ajustarse mejor a un descubrimiento de estilo diferente. –

4

Solo quería señalar un paquete Zeroconf NuGet alternativo: Zeroconf. No tiene dependencias nativas, por lo que no necesita instalar Bonjour para Windows o cualquier otra cosa.

Tiene soporte para .NET 4.5, WP8 y Win8.

+3

Una buena netiqueta incluiría una advertencia de que este es su propio proyecto que está anunciando. No va a marcarlo porque todavía es relevante, pero algo a considerar. – nathanchere

+1

No estoy seguro de por qué es importante ya que es una solución gratuita y de código abierto para el problema que tiene una implementación técnica mejor y más simple. Cualquiera que vaya a la página de Nuget o al sitio del proyecto GitHub verá que soy yo; no hay razón para negar nada. No hay ningún "producto" o dinero que se haga aquí. –

+0

Sería bueno si también tuviera modo de servidor para verificar. ¿Dónde está esta "implementación técnica mejor y más simple"? – kchoi

Cuestiones relacionadas