2012-03-23 2 views
5

Я работаю над игрой, использующей локальную сеть. Как и в большинстве многопользовательских игр, существует сервер-клиентская система. Компьютер A запускает экземпляр программы, создает сервер и ждет; Компьютер B делает то же самое. Теперь компьютер C запускает программу, я хочу, чтобы он мог видеть компьютеры A и B, перечисленные там в качестве игровых серверов. Как я могу это сделать?
Чтобы перечислить все доступные серверы, простым решением может быть следующее: мне нужно проверить все IP-адреса в определенном диапазоне и посмотреть, отвечают ли они через мой конкретный порт или нет. Если да, значит, на нем запущен экземпляр игры и должен быть указан в списке серверов.
Является ли описанное выше решение хорошим? Я искал и получить этот кусок кода:Java-сетевая игра: список доступных серверов?

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"); 
      } 
    } 
} 

но занимает так много времени, и бесполезно. Если это неправильное решение, каковы другие способы?

ответ

1

Отправить сообщение обнаружить с помощью либо:

  1. многоадресной рассылки (используйте java.netMulticast гнездо)
  2. вещания (использование java.net.DatagramSocket) к сетям широковещательный адрес

Есть все серверы слушают это и отвечают «Я здесь» и, возможно, больше информации для дальнейшей настройки соединения (имя сервера, версия, использование порта x, udp или tcp и т. д.)

0

Вы можете использовать udp для этого; отправьте широковещательную рассылку, если сервер встал, и пусть аль-узлы прослушивают пакеты udp.

В соответствии с запросом, приведен пример кода на utp; тезисы - 2 класса, одно - сердце (которое бьется), а другое - слушатель.

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

Есть ли образец кода для UDP? – mehrmoudi

+0

Я добавил 2 класса в качестве примера кода; Я не думаю, что вы можете просто запустить его в качестве примера, потому что вы, вероятно, пропустите некоторые другие необходимые классы, но это показывает udp-трансляцию. – Tom

2

Если вы работаете в локальной сети, ваш метод может занять огромное количество времени и определенно не является лучшим решением.

Вы можете решить эту проблему, если ваши серверы периодически транслируют свои адреса в сети, и все клиенты слушают ее. Хороший пример можно найти в the Java Tutorials.

1

Лучший способ сделать это с чем-то вроде ZeroConf (также известный как Bonjour). Это то, что Apple использует для всех своих сетевых открытий в устройствах iTunes и iOS, чтобы они могли находить друг друга.

Я реализовал его Linux, Windows и OSX в приложениях на стороне сервера с большим успехом.

И есть большая поддержка на всех основных языках.

Нет необходимости повторно изобретать это колесо.

Смежные вопросы