2014-02-22 40 views
0

我目前正試圖通過實現服務器/客戶端結構來獲取RMI的基礎知識,其中客戶端可以調用服務器上的遠程操作,並且服務器可以調用客戶端功能:確保RMI只在一個服務器實例上運行

public class Client extends GenericRMI implements ClientInterface { 
    public ServerInterface server; 

    public Client() { 
    try { 
     String IP = InetAddress.getLocalHost().getHostAddress(); 

     server = (ServerInterface) Naming.lookup("//192.168.2.124/WServer"); 

     int uniqueID = (int) Math.round(Math.random() * 1000); 

     super.setUpRMI("WClient" + IP + "_" + uniqueID); 

     server.registerNewClient(IP, uniqueID); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

public void setUserID(int id) { 
    System.out.println("got my ID from the server: " + id); 
} 
} 

public class Server extends GenericRMI implements ServerInterface { 
private List<ClientInterface> clients; 

public Server() { 
    clients = new ArrayList<ClientInterface>(); 
    super.setUpRMI("WServer"); 
} 

public void registerNewClient(String IP, int uID) throws RemoteException { 
    try { 
     ClientInterface c = (ClientInterface) Naming.lookup("//" + IP + "/WClient" + IP + "_" 
       + uID); 
     int newID = clients.size(); 
     clients.add(c); 
     c.setUserID(newID); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
} 

和,在主函數:

new Server(); 
Thread.sleep(1000); 
new Client(); 

Thread.sleep(1000); 
new Client(); 

Thread.sleep(1000); 
new Client(); 

接口由

public interface ServerInterface extends Remote... 
定義

RMI設置

public class GenericRMI implements Remote, Serializable { 
protected Registry registry; 

public void setUpRMI(String bindName) { 
    if (registry == null) { 
     try { 
      registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); 
     } catch (ExportException e) { 
      // client and server on one PC 
     } catch (RemoteException e) { 
      e.printStackTrace(); 
     } 
    } 

    try { 
     Naming.rebind(bindName, this); 
    } catch (RemoteException | MalformedURLException e) { 
     e.printStackTrace(); 
    } 
    System.out.println("Started " + bindName); 
} 
} 

然而,輸出是像

Started WServer 
Started WClient192.168.2.124_501 
got my ID from the server: 0 
Started WClient192.168.2.124_655 
got my ID from the server: 0 
Started WClient192.168.2.124_771 
got my ID from the server: 0 

即使我調試它,服務器具有爲每個客戶端不同的ID。我想我在某個地方犯了一個可怕的錯誤,因爲我曾經認爲服務器只會運行一個實例。我怎樣才能做到這一點?

編輯 問題是;如果我調試registerNewClient()函數,各自的服務器對象更改爲每個客戶端: 服務器@ 7728992 服務器@ 5fbb71ac ... 即使我讓客戶端列表同步,它並沒有幫助。但是,使客戶端字段暫時服務器端導致它的空指針異常,表明它確實是一個新的實例。

回答

1

您確實只有一個實例正在運行。您只需調用new Server()一次,並且在任何情況下都無法將三個實例綁定到註冊表中的同一名稱。更有可能你對未同步的'clients'集合有一個併發問題。

+0

問題是;如果我調試registerNewClient()函數,各自的服務器對象更改爲每個客戶端: 服務器@ 7728992 服務器@ 5fbb71ac ... 即使我讓客戶端列表同步,它並沒有幫助。但是,使客戶端字段暫時服務器端導致它的空指針異常,表明它確實是一個新的實例。 – Zahlii

+0

您需要使GenericRMI擴展UnicastRemoteObject。在運動中,它根本不是一個遠程對象。 – EJP

+0

謝謝,我發現了這一點,當我注意到你的迴應! – Zahlii

相關問題