2012-03-23 15 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を使用できます。サーバーが起動していて、alノードがUDPパケットをリスンするようにする場合は、ブロードキャストを送信します。

リクエストに応じて、ここにutpのコード例を示します。 2つのクラス、1つは心臓(拍動)、もう1つはリスナーです。

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

これを行う最善の方法は、ZeroConfBonjourとも呼ばれます)のようなものです。 これは、iTunesとiOSデバイスでネットワークを発見するためにAppleが使用するもので、お互いに見つけることができます。

Linux、Windows、OSXをサーバー側アプリケーションに実装しました。

また、すべての主要な関連言語にも大きなサポートがあります。

この車輪を再発明する必要はありません。

関連する問題