2 Stimmen

Java, HttpUrlConnection. Problem mit getResponseCode()

Ich versuche, den einfachsten Simplest WebServer und Client unter Verwendung von HTTP zu erstellen. (Bitte sagen Sie mir nicht, dass ich Apache HTTPClient verwenden soll).

Client: Versuch, eine Datei auf den Server zu PUTen.

// **PUT**
if(REQUEST.toUpperCase().equals("PUT")) {

  File sourceFile = new File(fileName);

  if(!sourceFile.canRead()) {
      System.out.println("Have not access to this file...");
      return;
  }

  try {
      BufferedInputStream is = new BufferedInputStream(new FileInputStream(sourceFile));

      URL url = new URL("http://" + HOST+":"+PORT);
      System.setProperty("http.keepAlive", "true");
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setDoInput(true);
      connection.setDoOutput(true);

      connection.setRequestMethod("PUT");
      connection.setRequestProperty("Content-Type", "Application/octet-stream");
      connection.setRequestProperty("Content-Length",Long.toString(sourceFile.length()));
      connection.addRequestProperty("Content-disposition","attachment; filename="+fileName);

      BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());

      byte[] buf = new byte[sizeArr];
      int r = 1;
      while((r = is.read(buf)) > 0) {
          os.write(buf, 0, r);
      }
      os.flush();
      os.close();

      System.out.println("Waiting for the response...");//this is written to console

      System.out.println(connection.getResponseCode());//HERE infinite waiting
      is.close();

  } catch (MalformedURLException ex) {
      ex.printStackTrace();
  } catch (IOException ex) {
      ex.printStackTrace();
  }
  }

Auf dem Server: wenn Request == PUT , dann:

// **PUT**
if (header.toUpperCase().equals("PUT")) {
    System.setProperty("http.keepAlive", "true");
    String fileName = null;

    if((fileName = extract(request.toUpperCase(),"FILENAME=","\n")) == null) {
        fileName = "UnknownFile.out";
    }

    try {
    File sourceFile = new File(fileName);
    BufferedOutputStream osFile = new BufferedOutputStream 
        (new FileOutputStream(sourceFile));

    byte[] locbuf = new byte[sizeArr];
    int locr = 1;
    while((locr = is.read(locbuf)) > 0) {
        System.out.println("locr= "+locr);//this is written to console
        osFile.write(locbuf, 0, locr);
    }
    System.out.println("Ending to record the data to the file."); 
    //  this is NOT written to console
    osFile.flush();
    osFile.close();
    }
    catch(IOException ex) {
        os.write(CodeRequest("500 Internal Server Error").getBytes());
        os.close();
        ex.printStackTrace();
        return;
    }

    System.out.println("Trying to send 200 OK");
    os.write(CodeRequest("200 OK").getBytes());
    os.flush();
    os.close(); // where os = clientSocket.getOutputStream();
    }

Warum erhält der Client keine Antwort vom Server? Wenn ich die Endlosschleife des Clients unterbreche, würde der WebServer die Daten korrekt in der Datei speichern. Aber der Client wird nie erfahren, dass seine Datei normal auf den Server hochgeladen wurde. Wenn ich diese Anweisung auf Client auskommentiere:

// System.out.println(connection.getResponseCode());

Dann verlässt der Client die Schleife korrekt und wird beendet. Aber der Server schreibt dies nicht einmal in die Konsole:

while((locr = is.read(locbuf)) > 0) {
  System.out.println("locr= "+locr);//this is NOT written to console
  osFile.write(locbuf, 0, locr);
}

Der Server schreibt dies NUR in die Konsole:

localExcString index out of range: -1

ohne eine Fehlermeldung.

Was ist los?

3voto

Roger Orr Punkte 151

Ihr Beispielcode für den Server zeigt nicht die Deklaration und Initialisierung von "is". Ich vermute jedoch, dass, da die Sitzung am Leben erhalten wird, der Aufruf von is.read() blockiert wird, bis einige Daten eintreffen. Da Sie die Länge des Inhalts im Client festgelegt haben, würde ich erwarten, dass die Leseschleife beendet wird, wenn diese Datenmenge erfolgreich gelesen wurde.

0voto

BalusC Punkte 1034465

Sie müssen anrufen URLConnection#getInputStream() nach dem Schreiben, um tatsächlich senden. die Anfrage (und damit die Antwort) abrufen. Erst danach können Sie den Antwortstatus abfragen. Dies ist so implementiert, weil es länger dauern kann, den Request Body zu erstellen, als ihn tatsächlich zu senden, und auch, weil es eigentlich keinen Sinn macht, eine Anfrage zu haben, wenn man nicht an der Antwort interessiert ist.

Editar Entschuldigung, ich habe mich geirrt. Die getResponseCode() ruft bereits implizit getInputStream() .

Wie auch immer, ich habe einen kleinen Testfall erstellt (siehe SSCCE für weitere Informationen) und es funktioniert einfach gut. Probieren Sie es aus und sehen Sie, ob es auch in Ihrem Fall funktioniert.

Kunde:

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Test {

    public static void main(String[] args) throws Exception {
        String data = "Hello!";
        URL url = new URL("http://localhost:8080/playground/test");
        OutputStream output = null;

        try {
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("PUT");

            output = connection.getOutputStream();
            output.write(data.getBytes());

            System.out.println("Response code: " + connection.getResponseCode());
        } finally {
            if (output != null) try { output.close(); } catch (IOException ignore) {}
        }
    }
}

Server:

package mypackage;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Test extends HttpServlet {

    protected void doPut(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        InputStream input = null;

        try {
            input = request.getInputStream();
            int data;
            while ((data = input.read()) > -1) {
                System.out.write(data);
            }
            System.out.println();
        } finally {
            if (input != null) try { input.close(); } catch (IOException ignore) {}
        }
    }
}

Das Ergebnis sollte ein Response code: 200 im stdout des Clients und eine Hello! im stdout des Servers.

Ich hoffe, dies hilft bei der Suche nach der Ursache Ihres Problems.

0voto

rauch Punkte 1775

Auf dem Server:

String strFileLen = extract(request.toUpperCase().trim(),"CONTENT-LENGTH:","\n");
                long fileLength = 0;
                if(strFileLen != null) {
                fileLength = Long.parseLong(strFileLen.trim());
                System.out.println("fileLength= "+fileLength);
                };

                byte[] locbuf = new byte[sizeArr];
                int locr = 1;long sumLen = 0;

                if(fileLength != 0) {
                while((sumLen += (locr=is.read(locbuf))) != fileLength) {
                    System.out.println("sumLen= "+sumLen);
                    osFile.write(locbuf, 0, locr);
                }
                }

\=================================================== Das funktioniert gut.

0voto

Stephen C Punkte 665668

Welche Zeichenfolge ist die CodeRequest Methode im Servercode zurück? Ich denke, das Problem könnte darin liegen, dass Sie kein CRLF am Ende der Statuszeile und ein weiteres am Ende des Antwort-Headers einfügen. Für Details lesen Sie bitte die HTTP 1.1-Spezifikation .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X