2011-03-03 61 views
9

我試圖寫Java servlet來接收二進制數據請求和回覆他們,用HttpServletRequest.getOutputStream()HttpServletResponse.getInputStream()接收二進制數據。這適用於一個項目,該項目包含由Silverlight客戶端發送的請求,該Servlet通過HTTP POST連接響應該請求。目前,爲了測試Servlet,我正在實現一個比Silverlight更熟悉的Java客戶端。發送和Servlet中

的問題是,在我的測試項目中,我從一個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編碼的字符串傳輸數據,或者如果我將原樣發送二進制數據。

預先感謝您。

回答

3

有一件事我能想到的是,你正在閱讀只request.getInputStream().available()字節,然後決定你已經擁有了一切。按照documentationavailable()將返回可以不受阻塞地讀取的字節數,但我沒有看到這是否實際上是保證是輸入流的全部內容任何提及,所以我傾向於認爲沒有這樣的保證。

我不知道如何最好找出什麼時候沒有更多的數據(也許Content-Length在請求可以幫助嗎?)沒有在EOF無限期阻塞的風險,但我會嘗試循環,直到讀取所有數據輸入流。爲了檢驗這一理論,你總是可以掃描進一步發生到流已知模式的輸入,也許>匹配,你所得到的初始<

+7

剛看完,直到'閱讀()''返回-1'。另請參閱每個基本Java IO書籍/教程的第1頁。 – BalusC 2011-03-03 12:40:19

+0

@BalusC:對。這就是我只能在文檔中瀏覽頭文件的情況。 – 2011-03-03 12:43:41

+0

你是對的,謝謝邁克爾!我使用'ByteArrayOutputStream'來寫入從ServletInputStream中讀取的字節,然後用'ByteArrayOutputStream.toByteArray()'獲得一個字節數組。 – jbatista 2011-03-03 12:44:22

8

要輸入流複製到輸出流中使用的標準方式:

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