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

时间:2018-12-11 00:01:01

标签: java networking objectoutputstream

我正在使用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();
        }
    }
}

我有一个ServerClient类,其想法是在服务器中创建Game类的实例并将其发送给客户端,然后在{ {1}}变量,然后在dataServer之间来回发送。

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

服务器输出

Client

预期产量(客户)

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

客户端类

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);
    }
}

问题

为什么在将矩阵发送给客户端时,如果正在服务器中对矩阵进行修改,则客户端会收到未修改的矩阵?

谢谢

1 个答案:

答案 0 :(得分:1)

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

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

(您可以使用ObjectOutputStream.writeUnshared,但由于组件对象将被共享,这会更加令人困惑。)

标准警告:请勿使用Java序列化。