2012-03-23 19 views
5

Estoy trabajando en un juego que usa una red de área local. Como la mayoría de los juegos multijugador, hay un sistema servidor-cliente. La Computadora A ejecuta una instancia de programa, crea un servidor y espera; La computadora B hace lo mismo. Ahora que Computer C ejecuta el programa, lo que quiero es que pueda ver las computadoras A y B listadas allí como servidores de juegos. ¿Cómo puedo hacer esto?
Para listar todos los servidores disponibles, una solución simple podría ser esta: necesito verificar todas las direcciones IP en un rango particular y ver si responden a través de mi puerto específico o no. En caso afirmativo, se ejecuta una instancia de juego y debe figurar en la lista de servidores.
¿Es la solución descrita arriba una buena? He buscado y sale este trozo de código:Juego de red Java: ¿cómo enumerar los servidores disponibles?

public void checkHosts(String subnet){ 
    int timeout=1000; 
    for (int i=1;i<254;i++){ 
     String host=subnet + "." + i; 
      if (InetAddress.getByName(host).isReachable(timeout)){ 
       System.out.println(host + " is reachable"); 
      } 
    } 
} 

pero es toma mucho tiempo y es inútil. Si no es la solución correcta, ¿qué otras maneras?

Respuesta

1

Enviar un mensaje descubrir utilizando:

  1. una multidifusión (use toma java.netMulticast)
  2. emisión (uso java.net.DatagramSocket) a las redes dirección de difusión

Tener todos los servidores lo escuchan y responden diciendo "Estoy aquí" y posiblemente más información para una configuración de conexión adicional (nombre del servidor, versión, puerto de uso x, udp o tcp, etc.)

0

puede usar udp para esto; envíe una transmisión si un servidor está activo y permita que todos los nodos escuchen los paquetes udp.

Según lo solicitado, aquí hay un código de ejemplo en utp; las tesis son 2 clases, una es el corazón (que late) y la otra es el oyente.

public class Heart extends Observable implements Runnable { 

private String groupName = "229.5.38.17"; 
private int port = 4567; 
MulticastSocket multicastSocket; 
DatagramPacket datagramPacket; 

public Heart(int connectionListenerPort, Observer...observers) { 
    for(Observer observer : observers) { 
     this.addObserver(observer); 
    } 
    try { 
     multicastSocket = new MulticastSocket(); 
     InetAddress group = InetAddress.getByName(groupName); 
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
     ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 
     objectOutputStream.writeObject(new Beat(connectionListenerPort)); 
     objectOutputStream.flush(); 
     objectOutputStream.close(); 
     byte[] buf = byteArrayOutputStream.toByteArray(); 
     datagramPacket = new DatagramPacket(buf, buf.length, group, port); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

@Override 
public void run() { 
    while(true) { 
     beat(); 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

private void beat() { 
    try { 
     multicastSocket.send(datagramPacket); 
     message(new Message(TYPE.INFO, KEY.MESSAGE, "Heart beat sent.")); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private void message(Message message) { 
    setChanged(); 
    notifyObservers(message); 
} 

} 

public class BeatListener extends Observable implements Runnable { 

private boolean run = true; 
private String groupName = "229.5.38.17"; 
MulticastSocket multicastSocket; 
private Network network; 

public BeatListener(Network network, Observer... observers) { 
    for(Observer observer : observers) { 
     addObserver(observer); 
    } 
    try { 
     multicastSocket = new MulticastSocket(4567); 
     multicastSocket.joinGroup(InetAddress.getByName(groupName)); 
    } catch (IOException e) { 
     error(e); 
     e.printStackTrace(); 
    } 
    this.network = network; 
} 

@Override 
public void run() { 
    while(run) { 
     DatagramPacket datagramPacket = new DatagramPacket(new byte[1500], 1500); 
     try { 
      multicastSocket.receive(datagramPacket); 
      if(!isLocalhost(datagramPacket.getAddress().getHostAddress())) { 
       Beat beat = getBeat(datagramPacket); 
       if(beat != null) { 
        network.setPeer(new Peer(datagramPacket.getAddress(), beat.getConnectionListenerPort())); 
        message(new Message(TYPE.NETWORK, KEY.NETWORK, network)); 
       } 
      } 
     } catch (IOException e) { 
      error(e); 
      e.printStackTrace(); 
     } 
    } 
} 

private void message(Message message) { 
    setChanged(); 
    notifyObservers(message); 
} 

private void error(Exception e) { 
    message(new Message(TYPE.ERROR, KEY.MESSAGE, e.getClass().getSimpleName())); 
} 

public void stop() { 
    run = false; 
} 

private boolean isLocalhost(String hostAddress) { 
    boolean isLocalhost = false; 
    Enumeration<NetworkInterface> networkInterfaces; 
    try { 
     networkInterfaces = NetworkInterface.getNetworkInterfaces(); 
     if(networkInterfaces != null) { 
      OUTER: 
      while(networkInterfaces.hasMoreElements()) { 
       NetworkInterface networkInterface = networkInterfaces.nextElement(); 
       Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); 
       if(inetAddresses != null) { 
        while(inetAddresses.hasMoreElements()) { 
         InetAddress inetAddress = inetAddresses.nextElement(); 
         if(hostAddress.equals(inetAddress.getHostAddress())) { 
          isLocalhost = true; 
          break OUTER; 
         } 
        } 
       } 
      } 
     } 
    } catch (SocketException e) { 
     error(e); 
     e.printStackTrace(); 
    } 
    return isLocalhost; 
} 

private Beat getBeat(DatagramPacket datagramPacket) { 
    Beat beat = null; 
    byte[] data = datagramPacket.getData(); 
    if(data != null) { 
     try { 
      ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data)); 
      beat = (Beat)objectInputStream.readObject(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 
    return beat; 
} 

} 
+0

¿Tiene algún código de muestra para UDP? – mehrmoudi

+0

Agregué 2 clases como código de ejemplo; No creo que solo puedas ejecutarlo como ejemplo, porque probablemente te pierdas algunas otras clases necesarias, pero muestra la transmisión udp. – Tom

2

Si está ejecutando en una red local, su método puede llevar una gran cantidad de tiempo y definitivamente no es la mejor solución.

Puede resolverlo haciendo que sus servidores transmitan periódicamente sus direcciones en la red y haga que todos los clientes lo escuchen. Un buen ejemplo se puede encontrar en the Java Tutorials.

1

La mejor manera de hacerlo es con algo como ZeroConf (también conocido como Bonjour). Esto es lo que Apple usa para todo su descubrimiento de redes en iTunes y dispositivos iOS para que puedan encontrarse entre sí.

Lo he implementado Linux, Windows y OSX en aplicaciones de servidor con gran éxito.

Y también hay un gran soporte en los principales idiomas relevantes.

No es necesario volver a inventar esta rueda.

Cuestiones relacionadas