【问题标题】:Sending and receiving binary data in Servlets在 Servlet 中发送和接收二进制数据
【发布时间】:2011-07-08 00:18:40
【问题描述】:

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

问题在于,在我的测试项目中,我将来自 Servlet 客户端的数据作为字节数组发送,并期望接收到具有相同长度的字节数组——只是它没有,而是我得到一个字节。因此,我在此处发布相关代码 sn-ps,希望您能指出我做错的地方,并希望提供相关的参考书目以进一步帮助我。

就这样吧。

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

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

提前谢谢你。

【问题讨论】:

    标签: http servlets post binary inputstream


    【解决方案1】:

    使用标准方式将输入流复制到输出流:

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

    【讨论】:

      【解决方案2】:

      我能想到的一件事是你只读取request.getInputStream().available() 字节,然后决定你已经拥有了一切。根据documentationavailable()会返回不阻塞可以读取的字节数,但是我没有看到任何提及这是否真的保证是输入流的全部内容,所以我倾向于假设没有做出这样的保证。

      我不确定如何最好地找出何时没有更多数据(请求中的 Content-Length 可能会有所帮助?)而不会冒无限期阻塞在 EOF 的风险,但我会尝试循环直到从输入流。要测试该理论,您始终可以扫描输入以查找在流中更远出现的已知模式,可能是与您得到的初始 &lt; 匹配的 &gt;

      【讨论】:

      • 阅读直到read() 返回-1。另请参阅每本基本 Java IO 书籍/教程的第 1 页。
      • @BalusC:对。这就是我只浏览文档中的标题所得到的。
      • 你是对的,谢谢迈克尔!我正在使用ByteArrayOutputStream 写入从ServletInputStream 读取的字节,然后使用ByteArrayOutputStream.toByteArray() 获取字节数组。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-11
      • 2017-10-11
      • 1970-01-01
      相关资源
      最近更新 更多