2011-03-03 3 views
9

Je tente d'écrire une servlet Java pour recevoir des requêtes de données binaires et y répondre, en utilisant HttpServletRequest.getOutputStream() et HttpServletResponse.getInputStream(). C'est pour un projet qui implique d'avoir une demande envoyée par un client Silverlight auquel cette servlet répond via une connexion HTTP POST. Pour le moment, pour tester le Servlet, j'implémente un client en Java avec lequel je suis plus familier qu'avec Silverlight. Le problème est que, dans mon projet de test, j'envoie les données d'un client Servlet sous la forme d'un tableau d'octets et que je m'attends à recevoir un tableau d'octets de la même longueur - mais ce n'est pas le cas. octet unique. Par conséquent, je poste ici les extraits de code pertinents dans l'espoir que vous pourriez me signaler où je me trompe et j'espère fournir une bibliographie pertinente pour m'aider.Envoi et réception de données binaires dans des servlets

Alors voilà.

Le servlet client gère les requêtes POST à ​​partir d'une page HTML très simple avec un formulaire que j'utilise comme frontal. Je ne suis pas trop inquiet à propos de l'utilisation de JSP etc, à la place je suis concentré sur la communication inter-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(); 
    } 
} 

Les poignées servlet serveur requêtes HTTP POST. Ceci est fait en recevant les demandes d'un client Servlet à des fins de test ci-dessus, mais à l'avenir, j'ai l'intention de l'utiliser pour des clients dans d'autres langues (en particulier, 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(); 
    } 
} 

Je suis coller à des tableaux d'octets au lieu d'utiliser BufferInputStream s jusqu'à présent parce que je ne l'ai pas encore décidé si je vais utiliser par exemple Chaînes codées en Base64 pour transmettre des données ou si je vais envoyer des données binaires telles quelles.

Merci d'avance.

Répondre

3

La seule chose que je peux penser est que vous lisez seulement request.getInputStream().available() octets, puis de décider que vous avez eu tout. Selon le documentation, available() retournera le nombre d'octets qui peuvent être lus sans bloquer, mais je ne vois aucune mention de savoir si cela est effectivement garanti pour être le contenu entier du flux d'entrée, donc je suis enclin à supposer que non ces garanties sont faites. Je ne suis pas sûr de savoir comment mieux savoir quand il n'y a plus de données (peut-être dans la demande peut aider?) Sans risquer de bloquer indéfiniment à EOF, mais je voudrais essayer de boucler jusqu'à avoir lu toutes les données de la flux d'entrée. Pour tester cette théorie, vous pouvez toujours analyser l'entrée pour un modèle connu qui se produit plus loin dans le flux, peut-être un > correspondant à la < initiale que vous obtenez.

+7

Il suffit de lire jusqu'à ce que 'read()' 'rendement -1'. Voir aussi la page 1 de chaque livre/tutoriel IO Java de base. – BalusC

+0

@BalusC: Droit. C'est ce que je reçois pour seulement écrémer les en-têtes dans la documentation. –

+0

Vous avez raison, merci Michael! J'utilise un 'ByteArrayOutputStream' pour écrire des octets lus à partir de' ServletInputStream', puis un tableau d'octets avec 'ByteArrayOutputStream.toByteArray()'. – jbatista

8

Pour copier flux d'entrée au flux de sortie utiliser la méthode standard:

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