Pergunta

Eu tenho um problema com o Jakarta Commons HttpClient. Antes da minha auto-escrito httpserver recebe a solicitação real lá é um pedido que é esvaziar completamente. Esse é o primeiro problema. O primeiro problema é resolvido. Ele foi causada por uma URLConnection desnecessário O segundo problema é que, às vezes, as pontas pedido de dados após a terceira ou quarta linha do pedido http:

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

Para a depuração Eu estou usando o TCPMonitor Axis. Há cada coisas é bom, mas o pedido vazio.

Como eu processar o fluxo:

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

Encontrada uma nova maneira de processar o fluxo. Eu li todos os parâmetros de cabeçalho e usar o 'conteúdo de comprimento' para a leitura dos dados de postagem.

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

Como eu enviar o pedido:

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

tem ninguém de ter uma ideia de como resolver estes problemas o problema?

Alex

Foi útil?

Solução

Pode ser a ver com a segunda condição em seu loop while, o isReady () método pode retornar falso quando a próxima leitura pode bloquear - mas você realmente não me importo se ele bloqueia ou não, então podemos simplesmente remover (você pode ler mais aqui: http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). Tente alterar a isto:

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

Agora você deve obter toda a solicitação.

Outras dicas

Eu não sei sobre o primeiro problema, mas acho que o seu segundo problema é devido a este:

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

Se o remetente não é rápido o suficiente o envio de dados, o receptor pode chamar is.ready() antes do próximo pacote foi enviado. Isso fará com que is.ready() para false retorno que fará com que o loop para parar.

A correção mínima é mudar essa linha para:

} while (byteIn != -1);

Editar

Mas, realmente, você precisa reescrever o método ao longo das linhas de resposta de @ simonlord. É uma péssima idéia para ler um fluxo de um byte sem buffer de cada vez. Você acaba fazendo uma chamada de sistema para cada chamada read, que é terrivelmente ineficiente.

EDIT 2

A razão que a remoção is.ready() causou atrasos é porque você não estava prestando a devida atenção para o protocolo HTTP. O problema era o código HttpClient estava mantendo o lado solicitação da conexão TCP aberta para permitir a conexão para ser reutilizado. O (mas sub-óptimas) solução simples teria sido para configurar HttpClient para fechar o lado pedido de ligação. Seu código teria então visto o EOF imediatamente. O que você realmente fez foi outra solução.

Francamente você não deve mesmo ser tentando para implementar o protocolo HTTP do lado do servidor, a menos que você está preparado para entender toda a especificação HTTP em profundidade e implementá-lo fielmente. As chances são de que uma implementação existente será mais rápido e mais confiável do que qualquer coisa que você pode bater juntos. O problema com a implementação de um subconjunto da especificação é que o servidor pode precisar falar com um navegador real que usa partes da especificação que você não se preocupou em implementar / teste.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top