【问题标题】:Java: List not being sent over socket correctly?Java:列表没有通过套接字正确发送?
【发布时间】:2012-08-13 21:06:10
【问题描述】:

我还有另一个套接字问题。与我的其他问题相比,这实际上相当奇怪。好的,所以我有一个客户端连接到服务器,该服务器通过 ObjectOutputStream 以恒定速率发送数据并通过 ObjectInputStream 接收数据。我有一个包含玩家坐标、游戏模式等的玩家对象列表。当客户端移动其玩家时,更新的坐标会发送到服务器,并且列表中的玩家对象也会更新。嗯,应该是更新了...我在服务器端打印出更改后的坐标,但是当我将列表发送给玩家打印出来时,坐标并没有改变。这是播放器类:

public static class Player implements Serializable {
    private static final long serialVersionUID = 8841477887428285969L;
    public int x, y, gamemode, ID;
    public String name;
    public Player(int x, int y, int gamemode, int ID, String name) {
        this.x = x;
        this.y = y;
        this.gamemode = gamemode;
        this.ID = ID;
        this.name = name;
    }

    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

服务器接收更新后的坐标并打印前后的位置:

Package.Client_Server main_packet = (Package.Client_Server) obj;
System.out.println(S00.getPlayerByID(ID).x + ", " + S00.getPlayerByID(ID).y);
S00.getPlayerByID(ID).setPosition(main_packet.x, main_packet.y);
System.out.println(S00.getPlayerByID(ID).x + ", " + S00.getPlayerByID(ID).y);

这里是客户端打印从服务器发送的自己的坐标的地方。 问题出在这里...更新后的坐标没有显示在这里,但仍然是旧坐标。难道我做错了什么? List 中仍然只有一个对象,因此它不仅仅是在某处创建更多对象...

Package.Server_Client main_packet = (Package.Server_Client) obj;
ID = main_packet.client_ID;
C00.players = main_packet.players;
System.out.println(C00.players.get(ID).x + ", " + C00.players.get(ID).y);
System.out.println(main_packet.players.get(ID).x + ", " + main_packet.players.get(ID).y); 
//I tried printing the list directly from the package as well but it isn't updated either...

哎呀,我什至会显示从服务器发送到包含列表的客户端的包:

public static class Server_Client implements Serializable {
    private static final long serialVersionUID = 5198487406288606819L;
    public int client_ID;
    public int online;
    public List<Player> players;
    public Server_Client(int client_ID, int online, List<Player> players) {
        this.client_ID = client_ID;
        this.online = online;
        this.players = players;
    }
}

我的整个问题是更新的坐标在服务器端的玩家列表中但是一旦列表被发送到客户端,更新的数据就不再更新......它和之前一样过程开始。这是套接字如何工作的问题,还是我只是可怕地陷入了一个小错误? List 不可能是问题,因为我将它交换为一组 Player 对象,但它仍然无法在客户端正确读取。帮忙?

编辑:也可以看到这种效果,因为当另一个客户端连接到服务器时,客户端 1 看不到客户端 2,因为列表没有更新,但客户端 2 可以看到客户端 1,就像他第一次连接到服务器时一样。客户端 1 的控制台总是说他是唯一连接的玩家(列表中有 1 个项目),而控制台 2 总是说有 2 个玩家连接(即使客户端 1 已断开连接)。因此,该列表不会被更新。那么是什么原因造成的呢?

这里是方法'getPlayerByID(int ID)':

public static Package.Player getPlayerByID(int ID) {
    for(int i = 0; i < players.size(); i++) {
        if(players.get(i).ID == ID) {
            return players.get(i);
        }
    }
    throw new NoSuchElementException("No player has the ID: " + ID);
}

【问题讨论】:

  • 你想要什么代码?我有很多东西要展示(尽管这实际上是我与这个问题相关的所有代码......)

标签: java list sockets object client


【解决方案1】:

确保您是否重复将相同的对象引用传递给ObjectOutputStream 的单个实例,您正在使用ObjectOutputStream.writeUnshared(Object) 来执行此操作,或者在该对象的写入之间调用ObjectOutputStream.reset()

如果您未能这样做,ObjectOutputStream 将看到该对象已写入并写入对先前序列化表单的引用,而不是您第一次编写该对象时的序列化状态。

【讨论】:

  • 好吧对不起,如果我在这里听起来很无知或没有受过教育,但是......什么?考虑到它总是会以某种方式发送相同的列表,这听起来可能是导致问题的原因,但我该如何实施修复? (对不起,我是一个相对较新的编码者)每次发送对象时我是否只在输出流上调用 .reset() ?
  • 哦等等!我知道了! reset() 成功了。太感谢了!此外,调用 reset() 会影响除此之外的其他任何东西吗?只是想知道,以防我稍后在弗里茨上发现其他东西
  • 或者,您可以使用writeUnshared(Object) 而不是writeObject(Object) 来实现相同的结果。
  • @MrDoctorProfessorTyler 是的。当您通过输出流发送第一个对象时,它会被缓存。如果您随后尝试更改对象并重新发送相同的对象,缓存将不知道该对象已更改,而是发送第一个对象,因为它已被缓存。它似乎在告诉您,您应该只在管道中发送不可变对象:) - 如果您让 .reset() 解决您的问题,您可能会受到性能影响。
  • 哦,好的,我明白了。这是一件好事。感谢 Alex 和 Dev!
猜你喜欢
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-19
  • 2014-01-11
  • 2021-01-11
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多