将序列化数据发送到 servlet 时出现 java.io.EOFException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6036622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:03:51  来源:igfitidea点击:

java.io.EOFException when sending serialized data to a servlet

javaservletsurlconnection

提问by rafi wiener

I'm tring to upload from my Java local application an object that will include a file to a server. My plan is that a servlet running on tomcat will get the object using the ObjectInputStreamin the doGetmethod. But I get an EOFException`.

我想从我的 Java 本地应用程序上传一个对象,该对象将包含一个文件到服务器。我的计划是在 tomcat 上运行的 servlet 将使用ObjectInputStreamindoGet方法获取对象。但我得到了一个EOFException`。

Here is the client code

这是客户端代码

import java.io.*;
import java.net.*;
public class Client {
    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("c:\rafi.txt");
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int n = 0;
        while (-1 != (n = inputStream.read(buffer))) {
            output.write(buffer, 0, n);
        }
        inputStream.close();
        File2 c2 = new File2(buffer);
        URL url = new URL("http://localhost:8080/servertest/Server");
        URLConnection cnx = url.openConnection();
        cnx.setDoInput(true);
        cnx.setDoOutput(true);
        cnx.setRequestProperty("Content-Type", "application/octet-stream");
        InputStream in = cnx.getInputStream();
        OutputStream out = cnx.getOutputStream();
        cnx.connect();
        ObjectOutputStream oos = new ObjectOutputStream(out);
        oos.writeObject(c2);
        oos.flush();
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(in);
        boolean readBoolean = ois.readBoolean();
        System.out.println(readBoolean);
        ois.close();
        in.close();
        out.close();
    }
}

here is the server's servlet

这是服务器的 servlet

import java.io.*;
import javax.servlet.*;
@WebServlet("/Server")
public class Server extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public Server() {
        super();
    }
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        InputStream in = req.getInputStream();
        OutputStream out = res.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(out);
        ObjectInputStream ois = new ObjectInputStream(in);

        File2 data_in;
        try {
            data_in = (File2) ois.readObject();
            byte[] a = new byte[data_in.mybytearray.length];
            System.arraycopy(data_in.mybytearray, 0, a, 0,data_in.mybytearray.length);
            System.out.println(a.toString());
            oos.writeBoolean(true);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            oos.writeBoolean(false);
        }
        finally{
            oos.close();
            }

        res.setContentType("java-internal/" + File2.class.getName());
        in.close();
    }
}

When I debug the server side and run the client I get the exception in this row

当我调试服务器端并运行客户端时,我在这一行收到异常

ObjectOutputStream oos = new ObjectOutputStream(out);

This is the error I get

这是我得到的错误

SEVERE: Servlet.service() for servlet [test1.Server] in context with path [/servertest] threw exception
java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at test1.Server.doGet(Server.java:38)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

I saw this question, but i't didn't help me. I'm using tomcat 7.

我看到了这个问题,但我没有帮助我。我正在使用 tomcat 7。

采纳答案by BalusC

InputStream in = cnx.getInputStream();
OutputStream out = cnx.getOutputStream();

The URLConnection#getInputStream()will immediately send the HTTP request to the server in order to retrieve the response body. The way as you've written the code, this thus takes place beforeyou've written any bit to the HTTP request body. Hence the EOFExceptionon the server side.

URLConnection#getInputStream()会立即发送HTTP请求到服务器,以便检索响应主体。按照您编写代码的方式,这将您向 HTTP 请求正文写入任何内容之前发生。因此EOFException在服务器端。

You need to ask for the HTTP response body by URLConnection#getInputStream()afteryou've written the necessary data to the HTTP request body. Here's a rewrite:

你需要问的HTTP响应体URLConnection#getInputStream(),你已经写了必要的数据到HTTP请求主体。这是一个重写:

URLConnection connection = new URL("http://localhost:8080/servertest/Server").openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/octet-stream");

ObjectOutputStream oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeObject(c2);
oos.close();

ObjectInputStream ois = new ObjectInputStream(connection.getInputStream());
boolean readBoolean = ois.readBoolean();
ois.close();

System.out.println(readBoolean);

Also, since you're basically sending a HTTP POST request, you need to handle this in the servlet's doPost()method rather than the doGet()method.

此外,由于您基本上是在发送 HTTP POST 请求,因此您需要在 servlet 的doPost()方法而不是doGet()方法中处理它。



Unrelatedto the concrete problem: this isn't really the best way of sending files over HTTP. While it might work, this is very tight coupled to Java serialization mechanism. I'd suggest to send HTTP multipart/form-datarequests instead. This can be achieved by Apache HttpComponents Clienton the client side and Apache Commons FileUploadon the server side. This way the servlet is reuseable for other purposes, such as a HTML form with <input type="file">in the front. Also the client can this way be reused to upload files to other HTTP websites.

具体问题无关:这并不是通过 HTTP 发送文件的最佳方式。虽然它可能有效,但它与 Java 序列化机制非常紧密地结合在一起。我建议改为发送 HTTPmultipart/form-data请求。这可以通过客户端Apache HttpComponents Client和服务器端的Apache Commons FileUpload来实现。通过这种方式,servlet 可重用于其他目的,例如前面的 HTML 表单<input type="file">。客户端也可以通过这种方式重新用于将文件上传到其他 HTTP 网站。

回答by bo2x

I solved this pbm with on client side :

我在客户端解决了这个 pbm:

HttpURLConnection cnx = (HttpURLConnection) new URL("http://localhost:8080/web").openConnection();
cnx.setRequestMethod("PUT");