【问题标题】:ArrayList in serializable object not carrying over writeUnshared/readUnshared (over network)可序列化对象中的 ArrayList 未携带 writeUnshared/readUnshared(通过网络)
【发布时间】:2018-12-13 01:18:53
【问题描述】:

我正在开发一个围绕我自己的客户端-服务器架构构建的 Java 多人游戏。简而言之,客户端每秒请求服务器 World 对象的副本 30 次,并在收到它后,将其客户端副本设置为响应。这一切都是使用 Java 的标准网络 API 完成的。

我遇到的问题是我还在世界中存储了一个 Player 对象的 ArrayList,当我将一个 Player 添加到此列表中时,客户端没有得到更新。它仍然从服务器接收世界的副本,但它不是最新的。

我在过去的项目中遇到过类似的问题,它是由 write/readObject 引起的,通过使用 write/readUnshared 修复了它,但即使这样也不起作用。

以下是通信服务器端的重要内容:

String message;
int sum = 0;
while(active)
{
    message = "";
    try {
        message = in.readUTF();
    } catch (IOException e) {
        active = false;
        System.out.println("Lost connection with client " + socket.getInetAddress());
    }

    if(message.equals("GETWORLD"))
    {
        try {
            sum++;
            if(sum == 100)
                main.world.addPlayer(999, 2, 2);
            System.out.println("Client requested world (#" + sum + ")");
            System.out.println(main.world.players.size());
            out.writeUnshared(main.world);
            out.flush();
            System.out.println("Sent client world (#" + sum + ")");
        } catch (IOException e) {
            active = false;
            System.out.println("Lost connection with client " + socket.getInetAddress());
        }
    }

    if(message.equals("DISCONNECT"))
    {
        active = false;
        System.out.println("Client " + socket.getInetAddress() + " requested disconnect");
    }
}

然后是客户端:

Object read = null;
int sum = 0;
while(active)
{
    try {
        Thread.sleep((long)(1000 / 30.0));

        if(connected)
        {
            sum++;
            System.out.println("Asking server for world (#" + sum + ")");
            out.writeUTF("GETWORLD");
            out.flush();

            read = in.readUnshared();
            if(read instanceof World)
            {
                World temp = (World)read;
                System.out.println(temp.players.size());
                frame.panel.updateWorld((World)read);
                System.out.println("Got world from server (#" + sum + ")");
            }
        }
    } catch (InterruptedException | ClassNotFoundException e1) {
        active = false;
        e1.printStackTrace();
    } catch (IOException e2) {
        active = false;
        System.out.println("Lost connection with server @ " + socket.getInetAddress());
        frame.dispose();
        System.exit(0);
    }
}

显然 sum 变量是用于调试的。 我用一些输出进一步测试了这个,这就是让我害怕的地方:

Client log:
...
Asking server for world (#99)
1
Got world from server (#99)
Asking server for world (#100)
1
Got world from server (#100)
Asking server for world (#101)
1
Got world from server (#101)
...

Server log:
...
Client requested world (#99)
1
Sent client world (#99)
Client requested world (#100)
2
Sent client world (#100)
Client requested world (#101)
2
Sent client world (#101)
...

您可以在此处看到,即使请求编号匹配,World 对象中 Player 对象的数量也存在明显差异。

对于那些好奇的人来说,这是 World 和 Player 类的重要内容:

public class World implements Serializable
{

    public ArrayList<Room> rooms;
    public ArrayList<Player> players;

    private QuickMaths qm;

...

public class Player implements Serializable
{

    private double xPos;
    private double yPos;
    private Color color;

    int id;
    ...

如果这是一个漫长而简单的问题,我深表歉意。我不确定这是参考问题还是其他网络怪癖,但这真的让我发疯。提前致谢。

【问题讨论】:

  • 我正要给你写一个答案的时候它关闭了。您的问题与 writeUnshared 有关。子对象仍然是共享的,因此播放器不会被重写。每次写入后使用reset方法写入一个新对象。
  • 难以置信——我还没有在任何地方看到过这样的记录!!我会尝试这样做,看看它是否有效。谢谢你。 edit: 之后使用 reset() 实际上确实有效。问题解决了。
  • ahhh - 我希望他们不要关闭这个......无论如何,请参阅here:“请注意,上述规则仅适用于使用 writeUnshared 编写的基本级别对象,而不适用于任何要序列化的对象图中的可传递引用的子对象。"
  • @JB Nizet 我认为应该重新打开这个。虽然解决方案大致相同,但这里的用户依赖 writeUnshared,这通常会产生误导。也许应该编辑标题,但我认为这个问题不应该结束。无论如何,您的电话。
  • @zipo13 我重新打开了这个问题。

标签: java networking arraylist


【解决方案1】:

您的问题在于 writeUnshared,这有点误导。 阅读here

"请注意,上述规则仅适用于基础级别 用 writeUnshared 写入的对象,而不是任何可传递的 要序列化的对象图中的引用子对象。 "

这意味着播放器对象不会被写入两次,但会使用序列化树中对该对象的旧引用。

对此的解决方案是在每次写入调用后调用reset 方法,以确保不会再次引用旧写入的对象。

所以:

out.writeUnshared(main.world);
out.flush();
out.reset();

【讨论】:

    猜你喜欢
    • 2015-04-22
    • 1970-01-01
    • 2011-03-16
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多