【问题标题】:Java - Problems with serialized objects within serialized objectsJava - 序列化对象中的序列化对象问题
【发布时间】:2013-08-22 10:13:01
【问题描述】:

大家好,我正在制作一款有趣的游戏,我已经通过研究和阅读解决了大部分问题,但现在我陷入了困境。

游戏快速解释: 两个客户端连接到服务器并开始游戏。服务器执行所有计算并在每个周期向客户端发送一个序列化的 GameState 对象。 GameState 只是一堆显示玩家位置的变量和一些 getter/setter。这工作正常。但是,现在我在游戏状态中创建了一个导弹数组列表,导弹是一个单独的对象并且也是可序列化的。客户端和服务器都有相同的 GameState 类和 Missile 类副本。

当客户端按下空格键时会添加导弹,这会被服务器注册。我让服务器在游戏状态的服务器版本中打印导弹的数量。在客户端打印导弹的数量始终为零。这是我尝试仅将相关内容放入其中的一些代码。

服务器将对象发送给播放器,player.objectout只是将对象写入objectoutputstream

public void updatePlayerOutput(){
    GameState send = new GameState(gameState);
    leftPlayer.playerObjectOut(send);
    rightPlayer.playerObjectOut(send);
}

GameState 的主要部分(省略了 getter 和 setter)。左右=player1和player2

public class GameState implements Serializable {

private double leftX;
private double leftY;
private double rightX;
private double rightY;
private ArrayList<Missile> missiles;

public GameState(){
    missiles = new ArrayList<Missile>();
}

public GameState(GameState game){
    leftX = game.getLeftX();
    leftY = game.getLeftY();
    rightX = game.getRightX();
    rightY = game.getRightY();
    missiles = game.getMissiles();
}

导弹类

  public class Missile implements Serializable {

private double x;
private double y;

private double dX;

public Missile(double inX, double inY, double inDX){
    x = inX;
    y = inY;
    dX = inDX;
}

public Missile(Missile inMissile){
    x = inMissile.getX();
    y = inMissile.getY();
    dX = inMissile.getDX();
}

最后是客户端读取的地方。 panel 是一个 JPanel 并使用游戏状态来获取绘制图像的位置

while(true){
    gameState = (GameState)(ois.readObject());
    panel.setGameState(gameState);
    panel.repaint();
    updateOutput();
    }

另外在相关说明中(可能是我的主要问题的原因),在我链接的代码的第一部分中,我必须创建一个全新的 GameState 对象来发送。为什么是这样?如果我尝试仅发送 gameState 变量,则不会保留任何信息。谢谢:)

【问题讨论】:

    标签: java serialization


    【解决方案1】:

    所以,如果我理解正确的话,服务器有一个游戏状态,将它序列化,然后发送给玩家。玩家然后修改他们收到的游戏状态的内容,你会惊讶于服务器上的游戏状态不包含更新。

    这是意料之中的。序列化不会发送对对象的远程引用。它将对象转换为字节序列,发送此字节序列,然后由接收方根据字节序列重构对象。

    打个比方,使用序列化发送一个对象就像拿一份纸质文档并传真它。收件人在收到的传真上写的任何内容都不会神奇地出现在原始文档上。

    如果您希望服务器知道更改,客户端必须将更新发送到服务器。

    关于问题的最后一部分,如果我理解正确,您尝试将同一个对象多次发送到同一个 ObjectOutputStream,而接收者没有看到第一个对象状态与后续对象状态之间有任何区别。这也是意料之中的。第二次发送同一个对象只会发送对先前发送对象的引用。这对于支持多次引用同一对象的对象图是必要的。您需要调用reset() 来...重置流并能够发送已发送对象的新状态。

    【讨论】:

    • 啊啊没有。客户端通过 InputStream 将服务器更新为 BufferedReader。例如,如果玩家一按下左箭头,则“LEFT”被发送到服务器并且服务器更新它的 gamteState 以将玩家一移动到左侧。然后服务器将这个 gameState 的副本发送给两个玩家。客户端从不更新游戏状态,仅使用它来获取玩家/导弹的位置等。我是故意这样做的,以便只有服务器可以修改游戏,使其变得美观和安全
    • 那么,发送更新的客户端代码和接收玩家更改并更新游戏状态的服务器代码在哪里,因为这似乎是问题所在?
    • 感谢解决第二部分!由于我不在电脑旁,我无法提供密码 ATM。不过,如果这是问题所在,这似乎很奇怪。当我运行游戏时,我可以毫无问题地移动两个玩家,当我按下空间导弹时,会添加到服务器游戏状态。
    • 我只是重新阅读了这个问题,以准确了解问题所在。所以,如果我理解正确的话,当你在服务器端显示游戏状态时,它是正确的。然后你将这个游戏状态发送给客户端。但是客户端看不到更新的状态。然后要么服务器发送一个过时的状态副本,要么客户端不使用更新的副本,或者客户端存在与线程相关的可见性问题。没有代码,很难说。
    • 感谢您的快速回复,并对我迟到的回复感到抱歉!我刚刚实施了您的重置修复,它完全解决了我所有的问题!非常感谢!现在一切都很好:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2010-12-26
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多