登录 RMI 服务器

Loging in on an RMI server

我正在尝试实现一个可以通过 RMI 在网络上玩的 2 人游戏。我有一个 Game 接口和一个实现该接口的 GameImpl class。为了让客户端玩一个游戏,我有一个服务器 class,如下所示:

public class RMIServer {

    public RMIServer(int port) throws RemoteException, AlreadyBoundException {
        Registry registry = LocateRegistry.createRegistry(port);
        Game game = new GameImpl();
        registry.bind("Game", game);
    }

    public static void main(String[] args) throws RemoteException, AlreadyBoundException {
        RMIServer server = new RMIServer(1099);
    }

}

另一方面,客户端 class 如下所示:

public class RMIClient {

    RMIClient(String host, int port) throws RemoteException, NotBoundException {
        Registry registry = LocateRegistry.getRegistry(host, port);
        Game game = (Game) registry.lookup("Game");
        game.play();
    }

    public static void main(String[] args) throws RemoteException, NotBoundException {
        RMIClient client = new RMIClient("127.0.0.1", 1099);
    }

}

如果只有一名玩家需要通过网络玩游戏,则此实现效果很好。我现在遇到的问题是我想登录以便两个不同的玩家可以通过网络相互对战。主要问题是我真的不知道去哪里寻找可能的用户和他们所有的游戏以及如何查看他们的登录信息。

我考虑过在服务器中保留一个 Map<User, Game> 并在用户登录后注册正确的游戏,但我不知道如何进行登录或如何确保客户端可以访问正确的游戏。

感谢任何帮助

首先,您在极低的层面上解决了这个问题。除非你有充分的理由,否则你应该考虑使用更高级别的抽象,例如...

  1. Spring Framework and optionally also Spring Security Remoting RMI
  2. Enterprise JavaBeans
  3. Apache Camel

这些技术将允许您继续使用 RMI 作为 传输,而且还可以使用 Session Facade 轻松构建 组件

一个人做这些会很乏味。


澄清一下我的回答。您应该使用会话外观模式存储您的游戏对象。

这是您的核心问题...

I have no idea how to do the login then or how to make sure the client gets to the right game.

这是一个看似复杂的问题。

  1. "How to do the login" 是一个账户服务的实现(完成 tokens/cookies )
  2. "How to make sure the client gets the right game" 是 Session Scope 的一个实现,它可以保留您的游戏对象并 return 将其呈现给呈现正确 [=51] 的用户=].

当我使用 RMI 开发 2-player minesweeper game 时,我也在想同样的问题。首先,您必须想知道您希望如何创建游戏?

  1. 您想在前 2 名可用玩家之间创建游戏吗("play ASAP" 模式)?示例:

    - player1 connects
    - player2 connects
    - the server automatically starts a game between player1 and player2
    
  2. 请各位选手自己选择对手(沙龙)?示例:

    - player1 connects
    - player2 connects
    - player3 connects
    - player1 decides to start a game with player3
    

如果您决定采用第二种模式,这里有一种方法。

在服务器上,保留当前连接的玩家列表。每次客户端连接到服务器并成功登录时,将他添加到该列表中:

/** The connected players */
private List<Player> connectedPlayers;

同时准备一张地图,其中包含每个玩家关联的游戏实例(顺便说一句,你走对了!)。

/** The games currently being played */
private Map<Player, Game> gameList;

当两个玩家之间创建游戏时(玩家 1 想和玩家 2 一起玩),将他们添加到游戏列表中。

Game game = new Game(player1, player2);
this.gameList.put(player1, game);
this.gameList.put(player2, game);

如果您需要知道用户是否有空且尚未在游戏中:

public boolean isUserAvailable(String potentialOpponent) throws RemoteException {
    for (Entry<Player, Game> entry : this.gameList.entrySet()) {
        if (entry.getKey().getUsername().equals(potentialOpponent)) {
            return false;
        }
    }
    return true;
}

游戏结束后,将 2 名玩家从地图中移除。

this.gameList.remove(game.getPlayerHost());
this.gameList.remove(game.getPlayerClient());

我无法在此处 copy/paste 更多代码,但如果您需要灵感,可以在我的游戏中找到 source code。这些文件很有趣: