Pregunta

Tengo un problema con las Jakarta Commons HttpClient. Antes de que mi auto-escrito HttpServer recibe la petición real hay una petición, que está completamente vacío. Ese es el primer problema. El primer problema está resuelto. Fue causada por una URLConnection innecesaria El segundo problema es que a veces los datos de solicitud termina después de la tercera o cuarta línea de la petición http:!

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

Para la depuración estoy usando el Eje TCPMonitor. No todas las cosas está bien, pero la solicitud vacía.

¿Cómo puedo procesar la corriente:

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

encontrado una nueva manera de procesar la corriente. He leído todos los parámetros de cabecera y el uso de la 'Content-Length' para la lectura de los datos de envío.

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

¿Cómo puedo enviar la solicitud:

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

Tener alguno de ustedes una idea de cómo resolver estos problemas, el problema?

Alex

¿Fue útil?

Solución

Podría ser que ver con la segunda condición en su bucle while, el método isReady () podría devolver false cuando la próxima lectura podría bloquear - pero no me importa si bloquea o no, por lo que simplemente puede eliminar que (se puede leer más aquí: http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). Intente cambiar a esto:

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

Ahora usted debe obtener toda la solicitud.

Otros consejos

No sé sobre el primer problema, pero creo que el segundo problema se debe a lo siguiente:

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

Si el remitente no es suficiente rápida de enviar datos, el receptor puede llamar is.ready() antes de que el próximo paquete ha sido enviado. Esto hará que is.ready() para volver false que hará que el bucle se detenga.

La solución mínima es cambiar esa línea a:

} while (byteIn != -1);

Editar

Pero, en realidad, es necesario reescribir el método de la línea de respuesta de @ simonlord. Es una muy mala idea para leer un flujo sin búfer un byte a la vez. Se termina haciendo una llamada al sistema para cada llamada read, que es terriblemente ineficiente.

EDIT 2

La razón de que la eliminación de is.ready() causó retrasos se debe a que no estaban prestando la debida atención al protocolo HTTP. El problema fue el código HttpClient mantenía el lado petición de la conexión TCP abierta para permitir la conexión a ser reutilizado. La solución más sencilla (pero por debajo del óptimo) habría sido para configurar HttpClient para cerrar el lado petición de la conexión. Su código se habría visto entonces el EOF de inmediato. Lo que realmente hizo fue otra solución.

Francamente ni siquiera debería ser tratando para implementar el protocolo HTTP en el lado del servidor a menos que esté preparado para entender toda la especificación HTTP en profundidad y aplicar fielmente. Lo más probable es que una implementación existente será más rápido y más fiable que cualquier cosa que usted puede golpear juntos. El problema con la implementación de un subconjunto de la especificación es que su servidor puede necesitar hablar con un navegador real que utiliza partes de la especificación que usted no ha tomado la molestia de poner en práctica / prueba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top