Question

J'ai un problème avec les Jakarta Commons HttpClient. Avant mon auto-écrit HttpServer reçoit la demande réelle il y a une demande qui est complètement vide. C'est le premier problème. Le premier problème est résolu. Elle a été causée par un URLConnection inutile Le deuxième problème est, parfois les données de demande se termine après la troisième ou la quatrième ligne de la demande http:

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

Pour le débogage J'utilise l'axe TCPMonitor. Il toutes les choses est très bien, mais la demande vide.

Comment puis-je traiter le flux:

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

trouvé une nouvelle façon de traiter le flux. Je lis tous les paramètres d'en-tête et d'utiliser la « longueur de contenu » pour la lecture des données de poste.

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

Comment puis-je envoyer la demande:

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

Demandez à quelqu'un d'entre vous une idée de comment résoudre ces problèmes, le problème?

Alex

Était-ce utile?

La solution

Il est peut-être à voir avec la deuxième condition dans votre boucle while, la méthode isReady () peut retourner false lorsque la lecture suivante pourrait bloquer - mais vous ne se soucient pas vraiment si elle bloque ou non, afin que nous puissions simplement supprimer (vous pouvez en savoir plus ici: http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStreamReader.html#ready%28%29 ). Essayez de changer à ceci:

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

Maintenant, vous devriez obtenir la demande entière.

Autres conseils

Je ne sais pas le premier problème, mais je pense que votre deuxième problème est dû à ceci:

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

Si l'expéditeur est pas de données envoi rapide assez, le récepteur peut appeler is.ready() avant que le paquet suivant a été envoyé. Cela entraînera is.ready() pour revenir false qui provoquera la boucle d'arrêter.

Le correctif minimal est de changer cette ligne à:

} while (byteIn != -1);

EDIT

Mais vraiment, vous avez besoin de réécrire la méthode dans le sens de la réponse de @ simonlord. Il est une très mauvaise idée de lire un flux unbuffered un octet à la fois. Vous finissez par faire un appel système pour chaque appel read, qui est horriblement inefficace.

EDIT 2

La raison pour laquelle la suppression is.ready() a causé des retards parce que vous ne prêtiez pas attention appropriée au protocole HTTP. Le problème a été le code HttpClient maintenait le côté demande de la connexion TCP ouverte pour permettre la connexion à réutiliser. La solution simple (mais sous-optimale) aurait été de configurer HttpClient pour fermer le côté demande de la connexion. Votre code aurait alors vu immédiatement l'EOF. Ce que vous avez fait était une autre solution.

vous ne devriez même pas franchement essayer pour mettre en œuvre le côté serveur protocole HTTP, sauf si vous êtes prêt à comprendre la spécification HTTP entière en profondeur et mettre en œuvre fidèlement. Les chances sont qu'une implémentation existante sera plus rapide et plus fiable que tout ce que vous pouvez frapper ensemble. Le problème avec la mise en œuvre d'un sous-ensemble de la spécification est que votre serveur peut avoir besoin de parler à un véritable navigateur qui utilise des pièces de la spécification que vous ne l'avez pas pris la peine de mettre en œuvre / test.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top