2011-02-13 2 views
1

Java에서 RMI를 사용하여 서버/클라이언트 프로그램을 수행하고 있습니다. 서버가 충돌 할 때 문제가 발생하지 않으면 클라이언트는 RemoteException을 가져와 연결을 끊습니다.Java RMI 시간 초과 (충돌)

그러나 클라이언트가 고장 났을 때 문제가 있습니다. 내 서버는 Timer를 사용하여 모든 클라이언트 객체에 ping을 가하고 클라이언트에 연결이 없으면 RemoteException을 잡아냅니다.

그런 다음 서버에서 클라이언트 개체를 제거하기 만하면됩니다 (목록에서 제거). 그러나 프록시 클라이언트 개체를 사용하여 다른 작업을 시도하면 다른 RemoteException이 throw되기 때문에 불가능합니다. 이 문제를 어떻게 해결할 수 있습니까?

List<User> users; 
Map<User, IClient> clients; 

    class PingClients extends TimerTask { 
      public void run() { 
       for (IClient client : clients.values()) 
       try { 
        client.ping(); 
       } catch (RemoteException e) { 
        //removeClient(client); GENERATES REMOTEEXCEPTION 
       } 
      } 

    } 

    public boolean removeClient(IClient c) throws RemoteException{ 
      User u = c.getUser(); 
      users.remove(u); 
      clients.remove(u); 

      for (IClient client : clients.values()) 
       client.updateUsers(users); 
     } 
+0

클라이언트 프록시를 반복하는 방법을 보여주고 목록에서 삭제하는 방법을 알려주십시오. iterate에 iterator를 사용하고 remove 메소드를 사용하여 현재 프록시를 목록에서 제거하면 RemoteException이 발생하지 않습니다. –

+0

고객을 삭제하는 방법은 여전히 ​​Google에 표시되지 않습니다. removeClient 메소드의 내용은 무엇입니까? –

답변

1

첫 줄에는지도 대신 ConcurrentMap을 사용해야합니다. 이렇게하면지도에 동시에 액세스 할 수있어 많은 문제를 피할 수 있습니다. 당신은 (연결되지) 클라이언트를 제거 할 때 때문에 당신은 RemoteException을 얻을

1

IClient c 클라이언트를 사용할 수없는 경우 분명히 예외가 발생합니다 거기에 getUser()를 호출, 원격 객체 인 경우 .. 당신은 먼저 클라이언트에서 getUser() 메소드를 호출하면 분명히 RemoteException이 발생합니다.

당신은 이런 식으로 코드를 변경해야합니다

class PingClients extends TimerTask { 
     public void run() { 
      for (Iterator<Map.Entry<User, IClient>> it = clients.entrySet().iterator(); it.hasNext();) 
      Entry<User, IClient> entry = it.next(); 
      try { 
       IClient client = entry.getValue(); 
       client.ping(); 
      } 
      catch (RemoteException e) { 
       it.remove(); 
      } 
     } 
    } 

는 한 번에 하나의 스레드 만이지도에 액세스 할 수 있는지 확인하십시오.

2

+0

동시 수정 예외가 발생하지 않습니까? 이 모든 작업을 반복하면서 컬렉션을 수정합니다. – josefx

+0

네, 맞아요. 나는 대답을 업데이트 할 것이다. –

+0

감사합니다. 멍청한 실수... – Lightforce