Frage

Ich habe ein Problem mit dem Jakarta Commons Httpclient. Vor meinem selbst geschriebenen Httpserver erhält den realen Wunsch gibt es eine Anforderung, die völlig leer ist. Das ist das erste Problem. Das erste Problem gelöst ist. Es wurde von einer unnötigen URLConnection verursacht Das zweite Problem ist, manchmal die Anforderungsdaten enden nach der dritten oder vierten Zeile der HTTP-Anforderung:

POST / HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Host: 127.0.0.1:4232

Für das Debuggen Ich bin mit dem Achsen TCPMonitor. alle Dinge Es ist in Ordnung, aber die leere Anfrage.

Wie kann ich verarbeiten, um den Strom:

StringBuffer requestBuffer = new StringBuffer();

InputStreamReader is = new InputStreamReader(socket.getInputStream(), "UTF-8");

int byteIn = -1;
do {
    byteIn = is.read();
    if (byteIn > 0) {
        requestBuffer.append((char) byteIn);
    }
} while (byteIn != -1 && is.ready());

String requestData = requestBuffer.toString();

Gefunden einen neuen Weg, um den Strom zu verarbeiten. Ich lese alle Header-Parameter und verwenden Sie den 'Content-Length' zum Lesen der Post-Daten.

InputStream is = mySocket.getInputStream();
if (is == null) {
    return;
}
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));

// Read the request line
// ...
// ...

// Parse the header
Properties header = new Properties();
if (st.hasMoreTokens()) {
    String line = in.readLine();
    while (line != null && line.trim().length() > 0) {
        int p = line.indexOf(':');
        header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim());
        line = in.readLine();
    }
}

// If the method is POST, there may be parameters
// in data section, too, read it:
String postLine = "";
if (method.equalsIgnoreCase("POST")) {
    long size = 0x7FFFFFFFFFFFFFFFl;
    String contentLength = header.getProperty("content-length");
    if (contentLength != null) {
        try {
            size = Integer.parseInt(contentLength);
        } catch (NumberFormatException ex) {
        }
    }
    postLine = "";
    char buf[] = new char[512];
    int read = in.read(buf);
    while (read >= 0 && size > 0 && !postLine.endsWith("\r\n")) {
        size -= read;
        postLine += String.valueOf(buf, 0, read);
        if (size > 0) {
            read = in.read(buf);
        }
    }
    postLine = postLine.trim();
    decodeParms(postLine, parms);
}

Wie kann ich die Anfrage senden:

client.getParams().setSoTimeout(30000);

method = new PostMethod(url.getPath());
method.getParams().setContentCharset("utf-8");
method.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
method.addRequestHeader("Connection", "close");
method.setFollowRedirects(false);

byte[] requestXml = getRequestXml();

method.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(requestXml)));

client.executeMethod(method);

int statusCode = method.getStatusCode();

Hat jemand von euch eine Idee, wie diesen Problemen, das Problem zu lösen?

Alex

War es hilfreich?

Lösung

Es könnte mit der zweiten Bedingung in Ihrer while-Schleife zu tun, die isReady () Methode false könnte zurückkehren, wenn die nächste Lese blockieren könnte - aber man weiß nicht wirklich, wenn es blockiert ist oder nicht, so können wir einfach entfernen http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). Versuchen Sie, diese zu ändern:

byte[] buf = new byte[500];
while((is.read(buf))>-1){
  requestBuffer.append(new String(buf).trim());
  buf = new byte[500];
}

Nun sollten Sie die ganze Anfrage erhalten.

Andere Tipps

Ich weiß nicht, über das erste Problem, aber ich denke, Ihr zweites Problem auf diese Ursachen zurückzuführen ist:

} while (byteIn != -1 && is.ready());

Wenn der Absender nicht schnell genug ist, Daten zu senden, kann der Empfänger is.ready() aufrufen, bevor das nächste Paket gesendet wurde. Dies führt dazu, is.ready() false zurückzukehren, die die Schleife verursacht zu stoppen.

Die minimale Fix ist, dass die Linie zu ändern:

} while (byteIn != -1);

Bearbeiten

Aber wirklich, müssen Sie die Methode entlang der Linien von @ simonlord Antwort schreiben. Es ist eine wirklich schlechte Idee, ein ungepufferten Stream eines Byte zu einem Zeitpunkt, zu lesen. Sie am Ende dabei einen Systemaufruf für jeden read Anruf, der schrecklich ineffizient ist.

EDIT 2

Der Grund, dass das Entfernen is.ready() Verzögerungen verursacht ist, weil Sie nicht die richtige Aufmerksamkeit auf das HTTP-Protokoll zu zahlen waren. Das Problem wurde der Httpclient-Code wurde Beibehaltung der Anforderungsseite der TCP-Verbindung öffnet die Verbindung zu ermöglichen, wiederverwendet werden. Die einfache (aber suboptimale) Lösung wäre Httpclient konfiguriert hat, die Anfrage Seite der Verbindung zu schließen. Ihr Code würde dann die EOF sofort gesehen. Was Sie wirklich tat, war eine andere Lösung.

Ehrlich gesagt soll man nicht einmal sein versuchen das serverseitige HTTP-Protokoll zu implementieren, wenn Sie bereit sind, die gesamte HTTP-Spezifikation in der Tiefe zu verstehen und es getreu umzusetzen. Die Chancen sind, dass eine bestehende Implementierung schneller sein und zuverlässiger als alles, was Sie zusammen klopfen können. Das Problem mit einer Teilmenge der Spezifikation Implementierung ist, dass der Server zu einem echten Browser sprechen muß, dass Teile der Spezifikation verwendet, die Sie nicht die Mühe gemacht haben / Test zu implementieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top