有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javasocket传输

我有几个类同时运行,它们从服务器获取输入。两个都安装了插座

问题是,即使我在类之间传输相同的数据,但当数据到达时,它并不相同

以下是发送方法:

        private boolean transferBroadcastData() {
            boolean success = false;

            try {           
                Vector<Client> clientsList =
                    onlineList.getClientsList();

                for (Client client : clientsList) {
                        ObjectOutputStream objectOutputStream =
                            client.getObjectOutputStream();
                            objectOutputStream.writeObject(clientsList);
                            objectOutputStream.flush();
                }


                success = true;

            } catch (Exception ioException) {
                ioException.printStackTrace();
            }

            return success;
        }

以下是接收方法:

        while (true) {
                try {
                    Object object = objectInputStream.readObject();

                    if (object instanceof Vector<?>) {
                        String x = "I got it:\n";

                        Vector<Client> clients = (Vector<Client>) object;

                        for(Client c : clients) {
                            x += "\n" + c;
                        }

                        JOptionPane.showMessageDialog(ClientManager.this, x);

                        usersPanel.addClientsToList((Vector<Client>) object);
                    }

                    else if (object instanceof Message)
                        messagePanel.appendText((Message) object);


                } catch (ClassNotFoundException classNotFoundException) {
                    statusPanel.updateStatus("Error reading from socket");
                }
            }

当我收到所有客户的向量时,其中的元素是不同的。这不是我试图传递的向量的内容

我错过了什么


共 (1) 个答案

  1. # 1 楼答案

    问题可能与序列化/ObjectOutputStream的使用有关。当一个对象被序列化时,ObjectOutputStream会保留内部记录以“优化”序列化过程,因此如果将同一个对象序列化两次,它只会重复ID,假设该对象没有更改。例如,如果运行代码:

    ObjectOutputStream oos = new ObjectOutputStream();
    MyObject[] arr = new MyObject[]{myObject};
    oos.write(myObject);
    oos.write(arr);
    

    输出可能如下所示(请注意,不是实际格式,只是一个示例):

    [[myObject;id=357;foo=bar;baz=36;]]
    [[MyObject[];id=358;data={id=357}]]
    

    请注意,数组不会再次序列化该对象,而只是已序列化版本的id。如果你有代码,再进一步:

    ObjectOutputStream oos = new ObjectOutputStream();
    oos.write(myObject);
    myObject.setBaz(99999);
    oos.write(myObject);
    

    你最终会得到:

    [[myObject;id=357;foo=bar;baz=36;]]
    {id=357}
    

    请注意,即使对象只更改了内部id,也会序列化。诀窍在于,在编写对象时,需要清除ObjectOutputStream的内部状态,这可以通过reset()完成。从javadocs:

    Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream.

    因此,如果您使用上一个示例并添加重置:

    ObjectOutputStream oos = new ObjectOutputStream();
    oos.write(myObject);
    myObject.setBaz(99999);
    oos.reset();
    oos.write(myObject);
    

    您应该获得以下预期行为的输出:

    [[myObject;id=357;foo=bar;baz=36;]]
    [[myObject;id=358;foo=bar;baz=99999;]]
    

    需要注意的一点是,第二个序列化现在将被视为与原始序列化不同的对象。根据传输数据的方式和内部关系,如果对象彼此共享引用,并且希望维护这些关系,则必须小心不要过早重置流