readObject() 抛出 EOFException,尽管尚未写入任何数据

readObject() throws EOFException although no data is written yet

提问人:Samaranth 提问时间:1/30/2019 最后编辑:halferSamaranth 更新时间:1/31/2019 访问量:247

问:

我目前正在编写一个客户端-服务器应用程序,其中应将数据传输到服务器以处理数据。为了建立连接,我使用 ServerSocket 和 Socket,为了发送数据,我在客户端使用 OutputStream + ObjectOutputStream,在服务器端使用 InputStream + ObjectInputStream。连接当前在 localhost 上运行。

我尝试传输的对象是一个仅包含 String 参数的可序列化类。

我现在面临的问题是,一旦客户端的 OutputStreams 被初始化(这导致同时初始化服务器的 InputStreams),readObject() 就会立即抛出一个 EOFException,而不是等待来自客户端的输入。

我使用以下代码从客户端发送数据:

    public void send(DataSet dataSet) {
        if (!clientStreamsEstablished) {
            initiateClientStreams();
        }
        try {
            out.writeObject(dataSet);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

只有当我在UI中点击“提交”按钮时,才会调用此方法,因此它不会在应用程序启动时执行。

目前(已经尝试了大量其他方法,有和没有 while()、循环等)使用这种方法在服务器上读取:

    private void waitForInput(ObjectInputStream in, InputStream listeningPort) {
        boolean dataReceived = false;
        DataSet dataSet = null;

        System.out.println("waiting ...");
        while (!dataReceived) {
            try {
                Object temp = in.readObject(); // <-- EOFException is thrown here
                boolean test = false;
                if (temp instanceof DataSet) {
                    dataSet = (DataSet) temp;
                }
            } catch (ClassNotFoundException | IOException e) {
                e.printStackTrace();
                break;
            }
        }

        System.out.println("Test 2: " + dataSet.toString());

        if (dataReceived) {
            waitForInput(in, listeningPort);
        }
    }

一旦服务器上的客户端线程到达这一行(参见上面的代码注释),我就会得到这个堆栈跟踪:

java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2626)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1321)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
    at com.labdashboardserver.ClientThread.waitForInput(ClientThread.java:53)
    at com.labdashboardserver.ClientThread.run(ClientThread.java:43)
Exception in thread "Thread-2" java.lang.NullPointerException
    at com.labdashboardserver.ClientThread.waitForInput(ClientThread.java:65)
    at com.labdashboardserver.ClientThread.run(ClientThread.java:43)

堆栈跟踪的第二部分包含 NullPointerException 的原因很明显,因为由于 EOFExcpetion,dataSet 永远不会初始化。

但是,从我的角度来看,readObject() 应该阻止并等待客户端发送任何数据,然后再开始读取它并抛出 EOF。我觉得我通读了一半的 Stack Overflow 和其他论坛来寻找答案,但我找到的文章只讨论阅读文件或只是立即关闭的临时流。

编辑

在调用 main 方法中的 UI 之前,我初始化连接:

    public static void main(String[] args) {
        connector = new LabConnector();
        connector.run();
        if (connector.getConnectionEstablished()) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        frame = new LabUI();
                        frame.setVisible(true);
                    } catch (Exception e) {
                        JOptionPane.showMessageDialog(null,
                                "Error Message:\n" + e.getMessage() + "\nProgram shutting down!", "Critical Error", 0);
                    }
                }
            });
    }

在 LabConnector 类中,我像这样初始化流和连接:

    public void run() {
        try {
            establishConnection();
        } catch (UnknownHostException e) {
            retryConnection(e);
        } catch (IOException e) {
            retryConnection(e);
        }

        if (connectionEstablished) {
            initiateClientStreams();
        }

    }

    private void establishConnection() throws UnknownHostException, IOException {

        client = new Socket(HOST_IP_ADRESS, HOST_PORT);

        JOptionPane.showMessageDialog(null, "Connected to Server!");

        connectionEstablished = true;

    }

    private void initiateClientStreams() {
        try {
            sendingPort = client.getOutputStream();
            out = new ObjectOutputStream(sendingPort);
            clientStreamsEstablished = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
Java 套接字 eof objectinputstream 对象outputstream

评论

1赞 Steve Smith 1/30/2019
您正在尝试读取一个对象两次,但只发送一次?尝试签入 in.available()。
0赞 Samaranth 1/30/2019
@SteveSmith 我不完全确定你的确切意思,因为客户端上唯一的 .write() 命令在我的帖子中提到的 send-method 中,但我会附加一些构建连接的类的更多代码,以防万一。
1赞 Samaranth 1/30/2019
@SteveSmith好建议!现在,当将 readObject() 置于以下条件时,它可以工作: if(in.available >= 0) { /*readObject()-call*/ }
2赞 user207421 1/30/2019
发生这种情况是因为对等方已关闭连接。使用并不能解决这个问题,或者其他任何事情,而且由于它永远不会返回 -1,因此测试它 >= 0 完全可以完成深蹲。检查发送代码。EOFExceptionavailable()
1赞 basin 1/30/2019
@user207421是对的。客户端可能在向有线发送任何内容之前就死了。它应该刷新,shutdownOutput(),然后才关闭

答: 暂无答案