【问题标题】:Unexpected behavior sending object through socket in javajava中通过套接字发送对象的意外行为
【发布时间】:2023-03-31 07:49:01
【问题描述】:

我正在使用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 类的实例并将其发送到客户端,然后在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

服务器类

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

客户端类

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 networking objectoutputstream


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 所以,基本上在发送对象之后我必须调用 reset() 并且在客户端中,在我阅读之后我也必须重置,对吗?感谢您的建议
    • 这是一种处理方式。使用另一个ObjectOutputStream 更为常见,尽管这意味着再次发送类描述符数据,这可能不是什么大问题。
    猜你喜欢
    • 2014-01-11
    • 2021-01-11
    • 2012-08-29
    • 1970-01-01
    • 2012-03-13
    • 2015-08-31
    • 2014-03-24
    • 2017-03-20
    相关资源
    最近更新 更多