Тайм-ауты Java RMI (происходит сбой) - PullRequest
1 голос
/ 13 февраля 2011

Я делаю сервер / клиентскую программу на Java, используя RMI. Когда происходит сбой сервера, это не проблема, клиенты получают RemoteException и отключаются.

Однако у меня проблемы при сбое клиентов. Мой сервер использует таймер для проверки всех клиентских объектов время от времени, когда он не получает никакого соединения с клиентом, он обнаружит RemoteException.

Затем предполагается удалить клиентский объект с сервера (просто удалив его из списка), но это невозможно, потому что, когда я пытаюсь что-либо сделать с прокси-клиентским объектом, он вызывает другое RemoteException. Как я могу решить эту проблему?

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

Ответы [ 3 ]

2 голосов
/ 13 февраля 2011

Вы получаете RemoteException, потому что, когда вы пытаетесь удалить клиента (который отключен), вы сначала вызываете метод 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();
            }
      }
  }

Убедитесь, что только один поток имеет доступ к карте одновременно.

1 голос
/ 13 февраля 2011

Если IClient c является вашим удаленным объектом, вызов getUser() для него, очевидно, вызовет исключение, если клиент недоступен ..

1 голос
/ 13 февраля 2011

Первая строка, вы должны использовать ConcurrentMap вместо карты. Это избавит вас от многих неприятностей из-за одновременного доступа к вашей карте.

...