在 java 中通过套接字发送对象的意外行为

Unexpected behavior sending object through socket in java

我正在使用 ObjectOutputStream 通过 Java 中的套接字发送 POJO,POJO 在下面

import java.io.Serializable;

public class Game implements Serializable {
    private static final long serialVersionUID = 4367518221873521320L;
    private int[][] data = new int[3][3];

    Game() {
        for (int x = 0; x < 3; x++) {
            for (int y = 0; y < 3; y++) {
                data[x][y] = 0;
            }
        }
    }

    int[][] getData() {
        return data;
    }

    public void setData(int[][] data) {
        this.data = data;
    }

    void printMatrix() {
        for (int x = 0; x < 3; x++) {
            for (int y = 0; y < 3; y++) {
                System.out.print(data[x][y] + " ");
            }
            System.out.println();
        }
    }
}

我有一个ServerClientclasses,想法是在服务器中创建一个Gameclass的实例并发送它发送给客户端,然后在 data 变量中执行更改,并在 ServerClient.

之间再次来回发送它

正在发送对象,但其内容不是预期的。

服务器输出

Waiting
Connected server
0 0 0 
0 0 0 
0 0 0 
Writing
0 0 0 
0 1 0 
0 0 0 

预期输出(客户端)

Connecting...
Connected client
Reading
0 0 0 
0 0 0 
0 0 0 
Reading
0 0 0 
0 1 0 
0 0 0

实际输出(客户端)

Connecting...
Connected client
Reading
0 0 0 
0 0 0 
0 0 0 
Reading
0 0 0 
0 0 0 #<-- there is no 1
0 0 0

服务器class

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    void start(int port) throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("Waiting");
        Socket socket = serverSocket.accept();
        System.out.println("Connected server");

        Game game = new Game();
        game.printMatrix();

        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

        System.out.println("Writing");
        oos.writeObject(game);

        game.getData()[1][1] = 1;
        game.printMatrix();
        oos.writeObject(game);
    }

    public static void main(String[] args) throws Exception {
        new Server().start(8082);
    }
}

客户class

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client {
    public void connect(String host, int port) throws Exception {
        System.out.println("Connecting...");
        Socket socket = new Socket(host, port);
        System.out.println("Connected client");

        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

        System.out.println("Reading");
        Game game1 = (Game) ois.readObject();
        game1.printMatrix();
        System.out.println("Reading");
        Game game2 = (Game) ois.readObject();
        game2.printMatrix();

    }

    public static void main(String[] args) throws Exception {
        new Client().connect("localhost", 8082);
    }
}

问题

为什么当矩阵被发送到客户端时在服务器中被修改,而客户端收到的是未修改的矩阵?

谢谢

Java 序列化可以循环处理各种对象图。它通过发回引用而不是将对象序列化两次来实现。

第二次发送对象时,您只是发送一个引用。您需要调用 ObjectOutputStream.reset 流,关闭该流以替换为另一个流,或者最好使用不可变值对象。或者前两个和最后一个 - 为了能够使用反向引用,ObjectOutputStream 保留对所有发送的对象的引用,并且 ObjectInputStream 同样对所有接收的对象。

(您可以使用 ObjectOutputStream.writeUnshared 但这会变得更加混乱,因为组件对象将被共享。)

标准警告:不要使用 Java 序列化。