2013-01-21 32 views
-1

我在理解我正在編寫的程序的內部運行時遇到問題。 該程序應該是一個聯繫服務器並註冊自己的RMI客戶端。然後服務器應該在循環中調用客戶端上的方法。 但是,偵聽器未被添加。RMI調用不添加回調監聽器

請注意輸出。在服務器上添加偵聽器之後,該方法會輸出正確的大小,但運行服務器的線程不會,因爲列表保持爲空。爲什麼哦這是爲什麼發生?

客戶

public class GameClient extends Thread implements Remote, Client, ModelChangeListener<Client>{ 
private static final long serialVersionUID = -394039736555035873L; 
protected Queue<GameModelEvent> queue = new ConcurrentLinkedQueue<GameModelEvent>(); 


public GameClient(){ 

} 

public static void main(String[] args){ 
    GameClient client = new GameClient(); 
    client.start(); 
} 


protected void bind(){ 
    System.setProperty("java.rmi.server.codebase","file:bin/"); 
    try { 
     Registry registry = LocateRegistry.getRegistry(); 
     Client c = (Client)UnicastRemoteObject.exportObject(this, 10999); 
     Server stub = (Server) registry.lookup("Server"); 
     stub.registerClient(c); 
    } catch (RemoteException | NotBoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 



@Override 
public void run() { 
    super.run(); 
    bind(); 
    while(!Thread.interrupted()){ 
     System.out.print("."); 
     GameModelEvent event = queue.poll(); 
     while(event != null){ 

      System.out.println(event); 


      event = queue.poll(); 
     } 

     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      return; 
     } 
    } 

} 

    ..... 
} 

服務器

public class GameServer extends Thread implements ModelChangeListener<GameServer>, Server{ 
protected Queue<GameModelEvent> queue = new ConcurrentLinkedQueue<GameModelEvent>(); 
List<Client> clients = Collections.synchronizedList(new ArrayList<Client>()); 

public static void main(String[] args){ 
    GameServer server = new GameServer(); 
    server.start(); 
} 

protected void bind(){ 
    System.setProperty("java.security.policy","file:policy.policy"); 
    System.setProperty("java.rmi.server.codebase","file:bin/"); 

    if (System.getSecurityManager() == null) { 
     System.setSecurityManager(new SecurityManager()); 
    } 
    try { 
     String name = "Server"; 
     Server engine = new GameServer(); 
     Server stub = 
      (Server) UnicastRemoteObject.exportObject(engine, 0); 
     Registry registry = LocateRegistry.getRegistry(); 
     registry.rebind(name, stub); 
     System.out.println("ComputeEngine bound"); 
    } catch (Exception e) { 
     System.err.println("GameServer exception:"); 
     e.printStackTrace(); 
     System.exit(1); 
    } 
} 

public void run() { 
    super.run(); 
    bind(); 
    while(!Thread.interrupted()){ 
     System.out.print(clients.size()+ " "); 

      try { 
       for(Client c : clients) 
       c.modifyConnection(null); 
      } catch (RemoteException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     GameModelEvent event = queue.poll(); 
     while(event != null){ 

      System.out.println(event); 


      event = queue.poll(); 
     } 

     try { 
      Thread.sleep(2000); 
     } catch (InterruptedException e) { 
      return; 
     } 
    } 

} 
@Override 
public void registerClient(Client client) { 
    System.out.println("\nAdded client "+client); 
    clients.add(client); 
    System.out.println("clients size "+clients.size());  
} 
... 
} 

輸出

ComputeEngine bound 
0 0 0 0 
Added client Proxy[Client,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:[10.117.2.88:10999](remote),objID:[5c30c56:13c5dfe5faf:-7fff, 1084850783049542281]]]]] 
clients size 1 
0 0 0 0 0 

回答

2

GameServer你要綁定的實例是一個不同的實例你創建你的主要方法之一。

它是綁定的實例將接收RMI調用,而它是線程將使用的主要方法實例 - 因此您有兩個不同的客戶端列表。

GameServer更換行:

UnicastRemoteObject.exportObject(engine, 0); 

有了:

UnicastRemoteObject.exportObject(this, 0); 
+0

哦了一聲哭了出來!原因。搞砸了,我打算爲這一個downvote自己!:)謝謝。 Upvote並接受 –

+1

我不能downvote自己。獲得的經驗... –

+0

新鮮的一雙眼睛的奇蹟:-) –