2009-10-16 10 views
5

Je ne suis pas du tout un programmeur Java, j'essaie de l'éviter à tout prix, mais il faut que je l'utilise pour un cours (en Le professeur exige que nous utilisions Socket(), BufferedReader(), PrintWriter() et diverses autres choses, y compris la méthode readLine() de BufferedReader()Java, sockets, BufferedReader, et readline hang ... :(

Fondamentalement, c'est le problème que je suis ayant. la documentation indique clairement que readLine doit retourner une valeur nulle à la fin du flux d'entrée, mais ce n'est pas ce qui se passe.

Socket link  = new Socket(this.address, 80); 
BufferedReader in = new BufferedReader(new InputStreamReader(link.getInputStream())); 
PrintWriter out = new PrintWriter( new PrintWriter(  link.getOutputStream(), true)); 

out.print("GET blah blah blah"); // http request by hand 
out.flush(); // send the get please 

while((s=in.readLine()) != null) { 

    // prints the html correctly, hooray!! 
    System.out.println(s); 
} 

au lieu de terminer à la fin de l'HTML, je reçois un l blanc ine, 0 et une autre ligne vide, puis le suivant in.readLine() se bloque pour toujours. Pourquoi? Où est ma null?

J'ai essayé out.close() pour voir si Yahoo! était en train de faire une session http persistant ou quelque chose (que je ne pense pas que ce serait sans l'en-tête nous sommes prêts à le faire).

Tous les exemples de sockets Java que je trouve sur le net semblent indiquer le tandis que la boucle est la forme correcte. Je ne connais pas assez Java pour déboguer cela.

Répondre

8

Votre problème est l'encodage de contenu "chunked". Ceci est utilisé lorsque la longueur du contenu demandé au serveur Web n'est pas connue au moment du démarrage de la réponse. Il se compose essentiellement du nombre d'octets envoyés, suivi de CRLF, suivi des octets. La fin d'une réponse est signalée par la séquence exacte que vous voyez. Le serveur web attend maintenant votre prochaine requête (ceci est aussi appelé "request pipelining").

Vous avez plusieurs possibilités:

  • Utilisez la version HTTP 1.0. Cela entraînera la fermeture automatique de la connexion par le serveur Web lorsqu'une réponse a été envoyée complètement.
  • Spécifiez l'en-tête "Connection: close" lors de l'envoi de votre demande. Cela fermera également la connexion.
  • Analyser le contenu codé "chunked" correctement et traiter simplement cela comme si la réponse est maintenant terminée, ce qu'elle est.
+0

Cela a du sens. Je devais vérifier les en-têtes. Je vais juste utiliser http1.0. – jettero

+0

Oui, pour un exercice scolaire qui est la chose la plus sensée à faire. – Bombe

7

Donc vous lisez depuis un socket (vous ne le montrez pas dans votre code, mais c'est ce que je comprends du texte)? Tant que l'autre côté ne ferme pas la connexion, Java ne sait pas qu'il se trouve à la fin de l'entrée. Par conséquent, readLine() attend que l'autre partie envoie davantage de données et ne renvoie pas null.

+0

... lecture d'une prise, oui. J'ai ajouté cela à la question, merci. – jettero

4

Essayez GET url HTTP/1.0. Le HTTP/1.0 indique au serveur que vous ne pouvez pas gérer plus d'un document par connexion. Dans ce cas, le serveur doit fermer la connexion après vous avoir envoyé le résultat.

+0

Ouais, ça a du sens et ça marche.Dans d'autres langues, je fermerais simplement mon côté de la socket pour que le serveur web sache qu'il n'y aura qu'une seule requête ... mais quand je referme(), il semble fermer les deux côtés du lien. Existe-t-il un moyen de fermer exactement un côté? Suis-je en train d'interpréter ce qui se passe? – jettero

+0

Vous avez raison, l'appel à proximité de 'out' fermera également le flux entrant. IIRC, c'est un bug/une fonctionnalité dans la classe du gestionnaire d'URL Javas. –

0

Votre requête HTTP est incomplète sans 2 paires retour chariot + saut de ligne. Vous devriez probablement aussi appeler close après l'envoi de la requête:

out.print("GET /index.html HTTP/1.0\r\n"); 
// maybe print optional headers here 
// empty line 
out.print("\r\n"); 
out.flush(); 
out.close();