在 Servlet 中发送和接收二进制数据

发布于 2024-10-20 09:22:28 字数 3518 浏览 6 评论 0原文

我正在尝试使用 HttpServletRequest.getOutputStream()HttpServletResponse.getInputStream() 编写一个 Java Servlet 来接收二进制数据请求并回复它们。这是针对一个项目,该项目涉及 Silverlight 客户端发送请求,该 servlet 通过 HTTP POST 连接响应该请求。目前,为了测试 Servlet,我用 Java 实现了一个客户端,我对它比 Silverlight 更熟悉。

问题是,在我的测试项目中,我将来自 Servlet 客户端的数据作为字节数组发送,并期望收到具有相同长度的字节数组 —— 但事实并非如此,相反,我得到的是单个字节。因此,我在这里发布相关的代码片段,希望您能指出我做错的地方,并希望提供相关的参考书目来进一步帮助我。

所以就这样吧。

客户端 servlet 处理来自一个非常简单的 HTML 页面的 POST 请求,该页面带有一个我用作前端的表单。我不太担心使用 JSP 等,相反,我专注于使 Servlet 间通信有效

// client HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
  String firstName = (String) request.getParameter("firstname");
  String lastName = (String) request.getParameter("lastname");
  String xmlRequest = "<MyRequest><Person><Name Firstname=\""+firstName+"\" Lastname=\""+lastName+"\" /></Person></MyRequest>";

  OutputStream writer = null;
  InputStream reader = null;
  try {
    URL url = new URL("http://localhost:8080/project/Server");
    URLConnection conn = url.openConnection();
    conn.setDoInput(true);
    conn.setDoOutput(true);

    writer = conn.getOutputStream();
    byte[] baXml = xmlRequest.getBytes("UTF-8");
    writer.write(baXml, 0,baXml.length);
    writer.flush();
    // perhaps I should be waiting here? how?

    reader = conn.getInputStream();
    int available = reader.available();
    byte[] data = new byte[available];
    reader.read(data,0,available);
    String xmlResponse = new String(data,"UTF-8");

    PrintWriter print = response.getWriter();
    print.write("<html><body>Response:<br/><pre>");
    print.write(xmlResponse);
    print.write("</pre></body></html>");
    print.close();

  } finally {
    if(writer!=null)
      writer.close();
    if(reader!=null)
      reader.close();
  }
}

服务器 Servlet 处理 HTTP POST 请求。这是通过接收来自客户端 Servlet 的请求来完成的,用于上面的测试目的,但将来我打算将其用于其他语言(特别是 Silverlight)的客户端。

// server HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServetResponse response)
throws ServletException, IOException {
  ServletInputStream sis = null;
  try {
    sis = request.getInputStream();
    // maybe I should be using a BufferedInputStream 
    // instead of the InputStream directly?
    int available = sis.available();
    byte[] input = new byte[available];
    int readBytes = sis.read(input,0,available);
    if(readBytes!=available) {
      throw new ServletException("Oops! readBytes!=availableBytes");
    }

    // I ONLY GET 1 BYTE OF DATA !!! 
    // It's the first byte of the client message, a '<'.
    String msg = "Read "+readBytes+" bytes of "
                 +available+" available from request InputStream.";
    System.err.println("Server.process(HttpServletRequest,HttpServletResponse): "+msg);
    String xmlReply = "<Reply><Message>"+msg+"</Message></Reply>";
    byte[] data = xmlReply.getBytes("UTF-8");
    ServletOutputStream sos = response.getOutputStream();
    sos.write(data, 0,data.length);
    sos.flush();
    sos.close();

  } finally {
    if(sis!=null)
      sis.close();
  }
}

到目前为止,我一直坚持使用字节数组而不是使用 BufferInputStream,因为我还没有决定是否使用 Base64 编码的字符串来传输数据,或者是否发送二进制文件数据按原样。

先感谢您。

I'm attempting to write a Java Servlet to receive binary data requests and reply to them, using HttpServletRequest.getOutputStream() and HttpServletResponse.getInputStream(). This is for a project which involves having a request sent by a Silverlight client to which this servlet responds to through an HTTP POST connection. For the time being, to test the Servlet I'm implementing a client in Java which I'm more familiar with than Silverlight.

The problem is that in my test project I send the data from a Servlet client as a byte array and expect to receive a byte array with the same length -- only it doesn't, and instead I'm getting a single byte. Therefore I'm posting here the relevant code snippets in the hopes that you might point me where I'm doing wrong and hopefully provide relevant bibliography to help me further.

So here goes.

The client servlet handles POST requests from a very simple HTML page with a form which I use as front-end. I'm not too worried about using JSP etc, instead I'm focused on making the inter-Servlet communication work.

// client HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
  String firstName = (String) request.getParameter("firstname");
  String lastName = (String) request.getParameter("lastname");
  String xmlRequest = "<MyRequest><Person><Name Firstname=\""+firstName+"\" Lastname=\""+lastName+"\" /></Person></MyRequest>";

  OutputStream writer = null;
  InputStream reader = null;
  try {
    URL url = new URL("http://localhost:8080/project/Server");
    URLConnection conn = url.openConnection();
    conn.setDoInput(true);
    conn.setDoOutput(true);

    writer = conn.getOutputStream();
    byte[] baXml = xmlRequest.getBytes("UTF-8");
    writer.write(baXml, 0,baXml.length);
    writer.flush();
    // perhaps I should be waiting here? how?

    reader = conn.getInputStream();
    int available = reader.available();
    byte[] data = new byte[available];
    reader.read(data,0,available);
    String xmlResponse = new String(data,"UTF-8");

    PrintWriter print = response.getWriter();
    print.write("<html><body>Response:<br/><pre>");
    print.write(xmlResponse);
    print.write("</pre></body></html>");
    print.close();

  } finally {
    if(writer!=null)
      writer.close();
    if(reader!=null)
      reader.close();
  }
}

The server servlet handles HTTP POST requests. This is done by receiving requests the requests from a client Servlet for testing purposes above, but in the future I intend to use it for clients in other languages (specifically, Silverlight).

// server HttpServlet invokes this method from doPost(request,response)
private void process(HttpServletRequest request, HttpServetResponse response)
throws ServletException, IOException {
  ServletInputStream sis = null;
  try {
    sis = request.getInputStream();
    // maybe I should be using a BufferedInputStream 
    // instead of the InputStream directly?
    int available = sis.available();
    byte[] input = new byte[available];
    int readBytes = sis.read(input,0,available);
    if(readBytes!=available) {
      throw new ServletException("Oops! readBytes!=availableBytes");
    }

    // I ONLY GET 1 BYTE OF DATA !!! 
    // It's the first byte of the client message, a '<'.
    String msg = "Read "+readBytes+" bytes of "
                 +available+" available from request InputStream.";
    System.err.println("Server.process(HttpServletRequest,HttpServletResponse): "+msg);
    String xmlReply = "<Reply><Message>"+msg+"</Message></Reply>";
    byte[] data = xmlReply.getBytes("UTF-8");
    ServletOutputStream sos = response.getOutputStream();
    sos.write(data, 0,data.length);
    sos.flush();
    sos.close();

  } finally {
    if(sis!=null)
      sis.close();
  }
}

I have been sticking to byte arrays instead of using BufferInputStreams so far because I've not decided yet if I'll be using e.g. Base64-encoded strings to transmit data or if I'll be sending binary data as-is.

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

智商已欠费 2024-10-27 09:22:28

要将输入流复制到输出流,请使用标准方法:

InputStream is=request.getInputStream();
OutputStream os=response.getOutputStream();
byte[] buf = new byte[1000];
for (int nChunk = is.read(buf); nChunk!=-1; nChunk = is.read(buf))
{
    os.write(buf, 0, nChunk);
} 

To copy input stream to output stream use the standard way:

InputStream is=request.getInputStream();
OutputStream os=response.getOutputStream();
byte[] buf = new byte[1000];
for (int nChunk = is.read(buf); nChunk!=-1; nChunk = is.read(buf))
{
    os.write(buf, 0, nChunk);
} 
挽容 2024-10-27 09:22:28

我能想到的一件事是,您只读取 request.getInputStream().available() 字节,然后确定您已经拥有了所有内容。根据文档, available() 将返回可以在不阻塞的情况下读取的字节数,但我没有看到任何提及这是否实际上保证是输入流的全部内容,所以我倾向于假设没有做出此类保证。

我不确定如何最好地找出何时没有更多数据(也许请求中的 Content-Length 可以提供帮助?),而不会冒着在 EOF 处无限期阻塞的风险,但我会尝试循环直到读取来自输入流的所有数据。为了测试该理论,您始终可以扫描输入以查找流中进一步出现的已知模式,可能是与您获得的初始 < 匹配的 >

The one thing I can think of is that you are reading only request.getInputStream().available() bytes, then deciding that you have had everything. According to the documentation, available() will return the number of bytes that can be read without blocking, but I don't see any mention of whether this is actually guaranteed to be the entire content of the input stream, so am inclined to assume that no such guarantees are made.

I'm not sure how to best find out when there is no more data (maybe Content-Length in the request can help?) without risking blocking indefinitely at EOF, but I would try looping until having read all the data from the input stream. To test that theory, you could always scan the input for a known pattern that occurs further into the stream, maybe a > matching the initial < that you are getting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文