Comment puis-je envoyer une Réponse HTTP en utilisant seulement la norme réseau des bibliothèques?
Je travaille sur mon premier devoir en programmation web de la classe, ce qui est d'écrire un simple serveur web en Java. J'en suis au point où j'ai des données transmises en arrière et en avant, et à l'œil non averti, mon bébé serveur semble fonctionner correctement. Cependant, je ne peux pas trouver un moyen d'envoyer des réponses appropriées. (En d'autres termes, une défaillance de page de demande de montrer une 404-ish page HTML, mais il renvoie toujours un 200 OK état quand je l'ai vue en-têtes de réponse).
Je suis limitée pour être en mesure d'utiliser les bibliothèques du réseau pour la prise de gestion et d'e/S standard des bibliothèques pour lire et écrire des octets et des chaînes à partir d'un flux d'entrée. Voici quelques code:
De mon principal...
ServerSocket servSocket = new ServerSocket(port, 10); //Bind the socket to the port
System.out.println("Opened port " + port + " successfully!");
while(true) {
//Accept the incoming socket, which means that the server process will
//wait until the client connects, then prepare to handle client commands
Socket newDataSocket = servSocket.accept();
System.out.println("Client socket created and connected to server socket...");
handleClient(newDataSocket); //Call handleClient method
}
De la handleClient méthode...(à l'intérieur d'une boucle qui traite la demande de la méthode et le chemin d'accès)
if(checkURL.compareTo("/status") == 0) { //Check to see if status page has been requested
System.out.println("STATUS PAGE"); //TEMPORARY. JUST TO MAKE SURE WE ARE PROPERLY ACCESSING STATUS PAGE
sendFile("/status.html", dataStream);
}
else {
sendFile(checkURL, dataStream); //If not status, just try the input as a file name
}
De sendFile méthode...
File f = new File(where); //Create the file object
if(f.exists() == true) { //Test if the file even exists so we can handle a 404 if not.
DataInputStream din;
try {
din = new DataInputStream(new FileInputStream(f));
int len = (int) f.length(); //Gets length of file in bytes
byte[] buf = new byte[len];
din.readFully(buf);
writer.write("HTTP/1.1 200 OK\r\n"); //Return status code for OK (200)
writer.write("Content-Length: " + len + "\r\n"); //WAS WRITING TO THE WRONG STREAM BEFORE!
writer.write("Content-Type: "+type+"\r\n\r\n\r\n"); //TODO VERIFY NEW CONTENT-TYPE CODE
out.write(buf); //Writes the FILE contents to the client
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace(); //Not really handled since that's not part of project spec, strictly for debug.
}
}
else {
writer.write("HTTP/1.1 404 Not Found\r\n"); //Attempting to handle 404 as simple as possible.
writer.write("Content-Type: text/html\r\n\r\n\r\n");
sendFile("/404.html", sock);
}
Quelqu'un peut-il expliquer comment, dans la condition de sendFile, je peut modifier la réponse dans le bloc 404 (Comme je l'ai dit avant, les en-têtes de réponse montrent encore 200 OK)? Ce qui est en écoute la merde hors de moi, et je veux juste utiliser la classe HTTPResponse mais je ne peux pas. (Aussi, la longueur du contenu et le type ne sont pas affichés si f.existe == true).
Merci!
- Dans le code on ne voit pas, n'avez-vous jamais l'ajout de votre écrivain variable pour le flux de sortie? Aussi ce type de données sont de l'écrivain et à l'extérieur? (Je ne veux pas assumer)
- J'ai PrintWriter writer = new PrintWriter(chaussette.getOutputStream()); au tout début de la méthode. Désolé de ne pas y compris, en essayant de rester concis! Aussi, l'écrivain est PrintWriter, est DataOutputStream.
- Essayez de changer l'en-tête de l'écrivain, et la mettre dans une chaîne de caractères. puis l'ajouter à la outputStream dans la chaîne de format. Voir si cela aide. Vous pouvez également consulter, à ne pas appeler sendFile() à partir de votre autre. si 404.html n'est pas trouvé, vous pouvez vous retrouver avec une boucle infinie. Vous pourriez le faire dans un ... if(fichier n'existe pas) le fichier est celui que vous avez passé en, le reste du fichier est le 404 document .....Ensuite, faites votre try catch.
Vous devez vous connecter pour publier un commentaire.
Le problème que vous rencontrez est probablement lié à un manque
flush()
sur votrewriter
. Selon le type deWriter
vous utilisez les octets sont d'abord écrites dans une mémoire tampon qui doit être vidées dans le flux. Cela expliquerait pourquoiContent-Length
etContent-Type
sont manquants dans la sortie. Juste le rincer avant de vous écrire d'autres données dans le flux.Plus vous appelez
sendFile("/404.html", sock);
. Vous n'avez pas de poste de la méthode complète ici - mais je suppose que vous l'appelez de manière récursive à l'intérieur desendFile
et donc à envoyer le200 OK
statut de votre dossier/404.html
.Modifier Il me semble que dans la 404 de la situation, vous l'envoyez à quelque chose comme ceci:
...suivi par la page 404. Remarque les 200 ligne à la suite de la 404. C'est parce que votre 404 manipulation appelle
sendFile
, qui est sortie le 200 code d'état de réponse. C'est probablement la confusion entre le récepteur.Vieille réponse qui a manqué que:
Une réponse HTTP commence avec une ligne d'état, suivi (en option) par une série d'en-têtes, puis (éventuellement) comprend un corps de réponse. La ligne d'état et les en-têtes ne sont que des lignes dans un format défini, comme (à choisir aléatoirement exemple):
Pour mettre en œuvre votre petit serveur HTTP, je vous recommande d'avoir une lecture le spec et de voir ce que les réponses devraient ressembler. C'est un peu un bond conceptuel, mais ils sont vraiment juste des lignes de texte retourné selon un format convenu. (Eh bien, c'était un bond conceptuel pour moi il y a quelques années, de toute façon. J'étais habitué à des environnements plus complexes et les choses.)
Il peut aussi être utile pour faire des choses comme cela à partir de votre favori en ligne de commande:
...et appuyez sur Entrée. Vous obtiendrez quelque chose comme ceci:
...suivi par du code HTML de fournir une sympathique page 404. La première ligne est au-dessus de la ligne d'état, le reste sont des en-têtes. Il y a une ligne vide entre la ligne d'état/en-têtes, et la première ligne du contenu (par exemple, la page).
Basé sur vos symptômes rapportés, je pense que le vrai problème, c'est que vous n'êtes pas réellement en parler à votre serveur à tout! La preuve en est que 1) vous ne pouvez pas obtenir une réponse 404, et 2) une réponse 200 n'a pas le contenu, la durée et le type. Aucune de ces devrait être possible ... si vous êtes réellement en train de parler pour le code ci-dessus.
Peut-être:
Je vous suggère d'ajouter un peu de trace de l'impression /l'exploitation forestière à des points appropriés de votre code afin de confirmer qu'il est effectivement appelé.