One-Shot-HTTP-Server

v1per1987

Mitglied
Hallo Leute,

ich lese gerade ein Buch über Server und Servlets und da ist gleich am Anfang ein Programm, bei dem ein One-Shot-HTTP-Server eine GET-Anfrage beantworten soll. Man soll außerdem eine Datei, z.B. index.html in seinem Arbeitsverzeichnis haben, damit der Server auch etwas zurückschicken kann.

Wenn ich das Programm starte und anschließend in meinem Internet-Browser http://localhost:8080/index.html eingebe, kommt in der Konsole von meinem Eclipse folgende Ausgabe:

Anfrage: GET / HTTP/1.1
404 Not Found

Also die GET-Anfrage scheint er ja schonmal zu bekommen. Aber eigentlich sollte ja noch mehr ausgegeben werden. In welchem Ordner muss sich denn die index.html befinden, damit der Server auf die Anfrage antworten kann?

Hier ist noch der Programmcode für den HTTP-Server:

package httpServer;

import java.io.*;
import java.net.*;
import java.util.StringTokenizer;

public class OneShotHttpd{

public final static int HTTP_PORT = 8080;

public static void main(String[] args){
try{
ServerSocket listen = new ServerSocket(HTTP_PORT);
Socket client = listen.accept();
BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream()));
DataOutputStream os = new DataOutputStream(client.getOutputStream());
String request = is.readLine();
System.out.println("Anfrage: " + request);
StringTokenizer st = new StringTokenizer(request);
if((st.countTokens()==3) && st.nextToken().equals("GET")){
request = st.nextToken().substring(1);
if(request.endsWith("/") || request.equals(""))
request += "index.html";
sendDocument(os, request);
}
else
System.err.println("400 Bad Request");
is.close();
os.close();
client.close();
}
catch(IOException ioe){
System.err.println("Fehler: " + ioe.toString());
}
}
public static void sendDocument(DataOutputStream out, String file) throws IOException{
try{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] buf = new byte[1024];
int len;
while((len = in.read(buf, 0, 1024)) != -1){
out.write(buf, 0, len);
}
in.close();
}
catch(FileNotFoundException fnfe){
System.err.println("404 Not Found");
}
}
}

Wäre echt super, wenn ihr mir weiterhelfen könnt!
 
Mit diesen Zeilen hier:
Java:
String request = is.readLine();
System.out.println("Anfrage: " + request);
StringTokenizer st = new StringTokenizer(request);
if((st.countTokens()==3) && st.nextToken().equals("GET")){
request = st.nextToken().substring(1);
if(request.endsWith("/") || request.equals(""))
request += "index.html";
sendDocument(os, request);
setzt das Programm den String request zusammen. Dieser wird der Methode
Code:
 sendDocument(DataOutputStream out, String file)
als file-Parameter übergeben. Setze in Eclipse in dieser Zeile einen Breakpoint und starte den Server mit Debug (nicht mit Run).
Java:
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
Dann kannst du sehen, was für ein String in file steht. Falls Du mit dem Debugger in Eclipse nicht umgehen kannst/willst, tut es auch ein
Code:
System.out.println(file);
. Mit dieser Information müsstest du eigentlich in der Lage sein, den richtigen Speicherort herauszufinden. (Tipp: wenn dort ein relativer Pfad (kein / am Anfang) rauskommt, muss das File relativ zum Ordner liegen, aus dem der Server gestartet wurde.)
 
Hi nillehammer,

danke schonmal für deine Erklärung. Mit dem Debugger habe ich bisher tatsächlich noch nichts zu tun gehabt. Das Problem ist, dass das Programm bei mir gar nicht erst in den try-Zweig kommt (den von der sendDocument-Methode meine ich), sondern gleich in den catch-Zweig geht. Das hab ich mit System.out.println schon getestet.

So wie ich das verstehe, wird unter "http://www.localhost.com:8080/index.html" einfach nicht das file "html.index" gefunden, weshalb auch keine sinnvolle Antwort auf das request kommen kann.

Aber ich habe auch keine Ahnung, wohin ich das file machen soll, damit es beim request gefunden wird. Die ganzen Ordner im Projekt hab ich schon ausprobiert. Mit "Eigene Dateien" klappt es auch nicht. Ansonsten hab ich keine Idee wo das hin sollte damit er es findet wenn ich im Browser http://www.localhost.com:8080/index.html eingebe.

Hast du vielleicht eine Idee wo das hin muss, oder woran es noch liegen könnte, dass es nicht klappt?
 
Also, ich hab es jetzt nochmal ohne Eclipse gemacht und das Programm in der DOS-Eingabeaufforderung ausgeführt. Einfach nur mit der .java und .class datei zusammen in einem Ordner mit einer index.html.

Und da gibt er dann auch tatsächlich zurück:

Anfrage: GET / HTTP/1.1
index.html

und der Text aus der html-Datei, z.B. <html>Hello index.html!</html> wird im Browser angezeigt.

Es würde mich natürlich trotzdem interessieren wo die Datei sein müsste, damit es auch mit Eclipse geht bzw was man anders machen muss. Weiß das vielleicht jemand?
 
Zuletzt bearbeitet:
v1per1987 hat gesagt.:
Das Problem ist, dass das Programm bei mir gar nicht erst in den try-Zweig kommt (den von der sendDocument-Methode meine ich), sondern gleich in den catch-Zweig geht. Das hab ich mit System.out.println schon getestet.
Deswegen hätte ich das System.out.println auch vor den try-catch-Block geschrieben. Dass er das File nicht findet ist ja bekannt. Was wir hier herausfinden wollten war, wo er überhaupt danach sucht. Noch besser wäre es übrigens, im catch-Block die FileNotFound-Exception auch irgendwie auszuwerten (z.B.
Code:
printStackTrace()
) da hätte dann auch der Pfad drinnen gestanden, unter dem das Programm die Datei sucht (und nicht gefunden hat).
v1per1987 hat gesagt.:
Es würde mich natürlich trotzdem interessieren wo die Datei sein müsste, damit es auch mit Eclipse geht bzw was man anders machen muss. Weiß das vielleicht jemand?
Dazu wiederhole ich nochmal meinen Tipp:
(Tipp: wenn dort ein relativer Pfad (kein / am Anfang) rauskommt, muss das File relativ zum Ordner liegen, aus dem der Server gestartet wurde.)
 
Hi nilehammer,

das mit dem Pfad anzeigen funktioniert bei mir weder mit einem System.out.println() noch mit .printStackTrace()

Ich hab es so in die sendDocument-Methode eingefügt:

public static void sendDocument(DataOutputStream out, String file) throws IOException{
System.out.println(file);
try{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] buf = new byte[1024];
int len;
while((len = in.read(buf, 0, 1024)) != -1){
out.write(buf, 0, len);
}
in.close();
}
catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
System.err.println("404 Not Found");
}
}

Du hast schon so gemeint oder?

Bei dem System.out.println() bekomme ich nur "index.html" raus und bei dem .printStackTrace() kommt die Ausgabe

java.io.FileNotFoundException: index.html (Das System kann die angegebene Datei nicht finden)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at httpServer.OneShotHttpd.sendDocument(OneShotHttpd.java:40)
at httpServer.OneShotHttpd.main(OneShotHttpd.java:25)
404 Not Found
 
Zunächst, verwende für Java-Code bitte Java-Tags (das Tassensymbol) und nicht Zitat-Tags. Damit kann man den Code besser lesen.
Bei dem System.out.println() bekomme ich nur "index.html" raus und bei dem .printStackTrace() kommt die Ausgabe
Funktioniert doch! Der angegebene Pfad ist ein relativer Pfad, nämlich "index.html" D.h. die Datei muss in das aktuelle Verzeichnis, von dem aus das Java-Programm gestartet wurde. Wenn Du das Programm über den Play-Button von Eclipse startest, ist es das Projektverzeichnis. Wenn du es nach Fertigstellung von der Console aus startest, ist es das Verzeichnis, in dem die class mit der main liegt.

Du merkst also, dass der Code für den Server nicht so ganz optimal ist. Vielleicht wird das in dem Buch ja noch verbessert.
 

Zurück
Oben