HTTP Webserver: Externe Dateien werden nicht verwendet.

Semox

Bekanntes Mitglied
Hallo Forum

In meiner neuen Version eines Webservers, werden Bilder vom Browser nicht gefunden, obwohl die Angabe der Pfade relativ zum HTML Dokument sind. Woran kann das liegen? Die Index.html wird aus einem Byte-Array an die Ausgabe geleitet. Mein Browser zeigt eine identische HTML Datei an, jedoch werden weder die CSS Datei, die im selben Verzeichnis liegt, wie die index.html, als auch die Bilder in einem Ordner, nicht gezeigt. Um nicht zu sagen, sämtliche verlinkten Dateien, werden vom Browser nicht benutzt...

Hier ist mein Webserver:

Java:
package iserve;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer implements Runnable {

	private boolean killswitch = true;
	private byte[] content;
	private int port = 80;
	public Socket connection;

	WebServer(byte[] data, int port) {
		this.content = data;
		this.port = port;
	}

	/*
	 * Thread Handler mit der Kernausfuehrung des Webservers
	 * 
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		try {
			ServerSocket server = new ServerSocket(this.port);
			System.out.println("Akzeptiere Verbindung auf Port: "
					+ server.getLocalPort());
			while (killswitch) {
				try {
					connection = server.accept();
					System.out
							.println("Server ist bereit und wartet auf Anfrage.");
					OutputStream out = new BufferedOutputStream(connection
							.getOutputStream());
					out.write(content);
					out.flush();
					System.out.println(server.getLocalSocketAddress());
				} catch (Exception e) {
					System.out.println(e);
				} finally {
					if (connection != null)
						connection.close();
				}
			}
		} catch (Exception e) {
			System.err.println(e);
		}
	}

	public static void main(String[] args) {
		try {

			BufferedReader br = new BufferedReader(
					new InputStreamReader(
							new FileInputStream(
									"/home/user/workspace/WebSurf/bin/iserve/demosite/index.htm")));
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int b;
			while ((b = br.read()) != -1)
				out.write(b);

			int port = 5000;
			byte[] data = out.toByteArray();
			Thread t = new Thread(new WebServer(data, port));
			t.start();

		} catch (Exception e) {
			System.err.println(e);
		}
	}
}

Kann mir jemand erklären, warum das nicht geht? Müssen externe Dateien: Bilder, Stylesheets eine gesonderte Behandlung erfahren?

Viele Grüße,
Semo

P.S. Anbei die Demo-Site

EDIT:

Ok. Ich habe eine Idee. Es liegt meiner Meinung nach daran, daß ich dem Browser nur die reinen HTML Daten liefere, die dargestellt werden, worüber hinaus ich dem Browser aber nicht mitteile, wie Pfadanfragen (beim Bilder abholen) vom Webserver behandelt werden sollen. Somit weiß der Browser zwar, daß die Dateien im gleichen Ordner wie die index.html liegen, bzw. im image Ordner, jedoch wird die relative Pfadangabe nicht durch den Webserver abgefangen, der daraus einen harten Pfad liefert. So oder so ähnlich. Ich brauche ein File Objekt, daß da auf magische Weise eingepflanzt werden muß... Hmmm...

Nur weiß ich nicht recht auf welche Weise die Bilder übertragen werden können - als Byte Array? Hat jemand Ahnung wie ich das machen sollte?

Viele Grüße und Danke,
Semo
 

Anhänge

  • demosite.zip
    37,6 KB · Aufrufe: 0
Zuletzt bearbeitet:

Semox

Bekanntes Mitglied
Hallo zusammen,

Problem weitgehend gelöst. :) Damit werden externe Dateien, wie CSS, JS oder etwas anderes geladen und weitergereicht, ohne daß der Browser die genaue Struktur meines Dateisystems erhält. Alles wird in Objekte geladen und die über einen Puffer nach draußen gereicht.

Wermutstropfen:
Leider wird im Browser nicht das komplette Bild mitgeliefert. An der Stelle wo ich fis.read(content) benutze wird doch alles einer zu ladenden Datei in ein Byte-Array gepackt und in Zeile 67, 69 sowie 79 (read, write, flush) an den Browser geschickt. Warum wird dann im Browser nur ein Teil des Bildes angezeigt? Ich weiß nicht woran das liegt. ???:L

Ich würde mich freuen, wenn mir jemand dabei etwas helfen könnte. Vielen Dank.

Der aktuelle Code:

[Java]
package iserve;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io_OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer implements Runnable {

private static File wwwDir;
private File www;
private boolean killswitch = true;
private byte[] content;
private int port = 80;
public Socket connection;

WebServer(File startVerz, byte[] data, int portNo) {
try {
startVerz = startVerz.getCanonicalFile();
} catch (IOException e) {
System.err.println(e);
}
content = data;
port = portNo;
www = startVerz;
}

/*
* Thread Handler mit der Kernausfuehrung des Webservers
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
ServerSocket server = new ServerSocket(this.port);
System.out.println("Akzeptiere Verbindung auf Port: "
+ server.getLocalPort());

// Initialisiere Verarbeitungsschleife
while (killswitch) {
try {
connection = server.accept();
System.out
.println("Server ist bereit und wartet auf Anfrage.");
// Lesepuffer für Browseranfragen bereitstellen
BufferedReader bStr = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
// Ausgabepuffer für Ausgabestrom bereitstellen
OutputStream out = new BufferedOutputStream(connection
.getOutputStream());
// Anfrage vom Browser einlesen und zerlegen
String request = bStr.readLine();
System.out.println(request);
request = request.substring(4, request.length() - 9).trim();

//Wenn Anfrage sich auf nachliefern einer Datei bezieht...
if (request.length() > 1) {
FileInputStream fis = new FileInputStream(www + request);
fis.read(content);
// Ausgabe an Browser
out.write(content);
out.flush();
} else {
// Ausgabe an Browser
out.write(content);
out.flush();
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (connection != null)
connection.close();
}
}
} catch (Exception e) {
System.err.println(e);
}
}

/**
* Dateiinhalte binärer Art können mit dieser Methode an einen Client
* gesendet werden. Die Quelldatei beliebiger Größe wird in ein Byte-Array
* der Größe 1000 zerlegt und stückweise wieder in den Ausgabestrom gelegt.
*
* @param input
* InputStream, der eine Datei beschreibt, die gesendet werden
* soll
* @param output
* OutputStream, der dem Ausgabestrom folgen soll
*/
@SuppressWarnings("unused")
private static void sendFile(InputStream input, OutputStream output) {
try {
byte[] buffer = new byte[1000];
while (input.available() > 0) {
output.write(buffer, 0, input.read(buffer));
}
} catch (Exception e) {
System.err.println(e);
}

}

public static void main(String[] args) {
System.out.println(args[0]);
System.out.println(args[1]);

if (args.length <= 1) {
System.out.println("Error: Not enough Arguments.");
System.out
.println("Usage: java WebServer [website's home folder] [start file to return to browser]");
System.exit(0);
}
wwwDir = new File(args[0]);
if (!wwwDir.isDirectory()) {
System.out.println("Error: Argument 0 is not a Directory.");
System.out
.println("Usage: java WebServer [website's home folder] [start file to return to browser]");
System.exit(0);
}

try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(args[1])));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int b;
while ((b = br.read()) != -1)
out.write(b);
int port = 5000;
byte[] data = out.toByteArray();
Thread t = new Thread(new WebServer(wwwDir, data, port));
t.start();
} catch (Exception e) {
System.err.println(e);
}
}
}
[/Java]

Beste Grüße,
Semo

EDIT: Screenshot eingefügt.
 

Anhänge

  • Bildschirmfoto.jpg
    Bildschirmfoto.jpg
    102,9 KB · Aufrufe: 36
Zuletzt bearbeitet:
T

tuxedo

Gast
Das mit den Bildern liegt wohl daran:

Java:
input.available()

Du solltest das Ergebnis von read() auf -1 überprüfen statt available() abzufragen. Nur ein -1 definiert das Ende des Streams. Siehe dazu auch die JavaDoc von InputStream#read(). Ein available()==0 kann auch so mal vorkommen, ohne dass der Stream tatsächlich am Ende ist.

- Alex
 

Semox

Bekanntes Mitglied
Hallo Tuxedo

Danke für den wertvollen Tip. Das war des Problems Lösung. Verstanden habe ich das zwar nicht was die API da erklärt, aber zumindest weiß ich, daß ich zwar das Einlesen des erwarteten Contents befehle, jedoch nicht die Ausgabe an den Browser mache. Daher hier mein nun funktionierender vollständiger Mini-Webserver.

Java:
package iserve;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer implements Runnable {

	private static File wwwDir;
	private File www;
	private boolean killswitch = true;
	private byte[] content;
	private int port = 80;
	public Socket connection;

	WebServer(File startVerz, byte[] data, int portNo) {
		try {
			startVerz = startVerz.getCanonicalFile();
		} catch (IOException e) {
			System.err.println(e);
		}
		content = data;
		port = portNo;
		www = startVerz;
	}

	/*
	 * Thread Handler mit der Kernausfuehrung des Webservers
	 * 
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		try {
			ServerSocket server = new ServerSocket(this.port);
			System.out.println("Akzeptiere Verbindung auf Port: "
					+ server.getLocalPort());

			// Initialisiere Verarbeitungsschleife
			while (killswitch) {
				try {
					connection = server.accept();
					System.out
							.println("Server ist bereit und wartet auf Anfrage.");
					// Lesepuffer für Browseranfragen bereitstellen
					BufferedReader bStr = new BufferedReader(
							new InputStreamReader(connection.getInputStream()));
					// Ausgabepuffer für Ausgabestrom bereitstellen
					OutputStream out = new BufferedOutputStream(connection
							.getOutputStream());
					// Anfrage vom Browser einlesen und zerlegen
					String request = bStr.readLine();
					System.out.println(request);
					request = request.substring(4, request.length() - 9).trim();

					// Wenn Anfrage sich auf nachliefern einer Datei bezieht...
					if (request.length() > 1) {
						// Lesepuffer der Größe 1000 Byte
						byte[] buffer = new byte[1000];
						FileInputStream fis = new FileInputStream(www + request);
						// Ausgabe an Browser
						while (fis.available() > 0) {
							// Chunkweises Lesen und senden der Daten
							out.write(buffer, 0, fis.read(buffer));
						}
						out.flush();
					} else {
						// Ausgabe an Browser
						out.write(content);
						out.flush();
					}
				} catch (Exception e) {
					System.out.println(e);
				} finally {
					if (connection != null)
						connection.close();
				}
			}
		} catch (Exception e) {
			System.err.println(e);
		}
	}

	public static void main(String[] args) {
		System.out.println(args[0]);
		System.out.println(args[1]);

		if (args.length <= 1) {
			System.out.println("Error: Not enough Arguments.");
			System.out
					.println("Usage: java WebServer [website's home folder] [start file to return to browser]");
			System.exit(0);
		}
		wwwDir = new File(args[0]);
		if (!wwwDir.isDirectory()) {
			System.out.println("Error: Argument 0 is not a Directory.");
			System.out
					.println("Usage: java WebServer [website's home folder] [start file to return to browser]");
			System.exit(0);
		}

		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream(args[1])));
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int b;
			while ((b = br.read()) != -1)
				out.write(b);
			int port = 5000;
			byte[] data = out.toByteArray();
			Thread t = new Thread(new WebServer(wwwDir, data, port));
			t.start();
		} catch (Exception e) {
			System.err.println(e);
		}
	}
}

Das Serverchen steht zur freien Verfügung für jeden.

Viele Grüße,
Semo
 

HoaX

Top Contributor
Dein HTTP-Server hat aber noch einige Bugs, da würde ich lieber auf Jetty und Konsorten zurückgreifen, die sind auch nicht soooo groß.

Was bei dir fehlt ist z.B. die korrekte Auswertung der Header: Was wenn im ersten Aufruf nicht "GET /seiten/url" steht, sondern "GET /seiten/ur HTTP/1.0"? Oder bei einem POST? Es gibt noch viele weitere Fälle die behandelt werden sollten.
Nur weil es in einem Szenario ohne Fehler funktioniert heißt es nicht, dass es immer fehlerfrei funktioniert. Also sollte man noch nicht von "fertig" reden ;)
 

Semox

Bekanntes Mitglied
Hi HoaX

Ich möchte gern anführen, daß dieser Micro-Webserver nicht für eine produktive Umgebung gemacht ist. :) Es ist ein Versuch sich mit den Minimal-Anforderungen für einen funktionstüchtigen Server auseinanderzusetzen. Ehrlich gesagt, war es vor 3 Monaten eine Hausaufgabe, die ich schon längst in der Uni eingereicht habe. Jedoch, war das ein beschissenes Teil. Den alten Code will ich nicht zeigen. In wesentlich verbesserter und vekürzter Form habe ich ihn nochmal neu gemacht.

Wahrscheinlich ist ein Webserver schon 10 exp 10 exp 9 programmiert worden. Allein ich will das ganze Thema Stück für Stück lernen. :) Ich habe eher das Gefühl, daß der Server weniger Bugs hat - denn auch auf verschiedenen anderen Rechnern hat das bißchen Programm gut funktioniert. Du meinst bestimmt "Missing-Features". Wenn ja, dann in der Tat - es gibt allerhand Missing Features.

Wenn es echte Bugs gibt, dann bin ich froh, wenn ich das innerhalb meines Lieblingsforums ;) klären kann. Im Ernst, ich will mal einen Webserver bauen, der erweiterbar ist.

Da werfen viele Fragen ihren Schatten voraus, bevor ich überhaupt nur im Ansatz die Konsequenzen einer Lösung abschätzen kann. Deswegen ist der Weg das Ziel. Viele Anfänger werden sich bestimmt an diesem Thread erfreuen, deswegen hoffe ich, daß er viel Konstruktives zu bieten hat.

Also ist mein kommender Wunsch die Erweiterung des Servers um die Fähigkeit einer anständigen Verarbeitung von Header Anfragen.

Ich habe im Netz allerhand Header-Anfragen verschiedener Browser gefunden. Wie genau finde ich denn die Header heraus, die ich per Regex o.ä. filtern kann? Wo stehen diese? Gibt es einen festen Satz an Regeln, die man filtern könnte? Freue mich (und andere bestimmt auch) über Unterstützung!

Viele Grüße,
Semo

P.S. Will mit dem Krempel hier kein Geld verdienen, sondern der guten Sache der freien Software dienen! :toll:
 

Semox

Bekanntes Mitglied
Ich habe eine lange Liste mit verschiedenen MIME-Typen. Wie geht man damit nun um? Wenn man sich umschaut, dann ist es den meisten Browsern völlig egal, ob ein MIME angegeben wurde oder nicht. De Darstellung funktioniert trotzdem, oder nicht? Ist es sinnvoll MIME zu unterstützen? Ich versuch das einzubauen, aber sehe keinen Sinn darin.

Grüße,
Semo
 
T

tuxedo

Gast
Die Mime-Typen identifizieren Inhalte/Content. Ohne Mime könnte der Browser recht wenig Inhalte voneinander abgrenzen. Wenn er eine JPG, ein Flash-Video, ein MOV Video, eine XML, einen Textfile etc... lädt.. woher weiß er was er damit tun muss? Anzeigen, öffnen, Downloaden, mit einer Anwendung öffnen,..... Eben all das wird durch die Mime-Typen festgelegt. Wenn der Browser das ignoriert, dann führt ein Klick auf eine ZIP Datei wohl zur Anzeige des Inhaltes in byte-Form im Browser-Fenster, statt zu einem Download.

Für die Darstellung einer Webseite an sich ist MIME wohl nicht so wichtig. Aber der Webserver wird ja noch mehr als nur HTML ausliefern, oder?!

Siehe auch: SELFHTML: HTML / Multimedia / Mime-Typen fr Dateiformate
 
Zuletzt bearbeitet von einem Moderator:

Semox

Bekanntes Mitglied
Hallo tuxedo

Gut. Verstanden. Habe die Klasse um zumindest die folgende Methode erweitert:

Java:
private String[] setupMimeTypeArray() {
		try {
			int count = 0;
			int arrayindex = 0;
			BufferedReader in = new BufferedReader(new FileReader(
					"/home/user/workspace/WebSurf/bin/iserve/mime_types.txt"));
			String zeile = null;
			while (in.readLine() != null) {
				count++;
			}
			in.close();

			String[] mimeTypes = new String[count];
			BufferedReader in2 = new BufferedReader(new FileReader(
					"/home/user/workspace/WebSurf/bin/iserve/mime_types.txt"));
			while ((zeile = in2.readLine()) != null) {
				mimeTypes[arrayindex] = zeile;
				arrayindex++;
			}
			in2.close();
			return mimeTypes;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

Wie geht man nun weiter vor? Wie sieht denn die Response an den Browser aus, damit der weiß was er tun soll? Ich finde zwar allerhand Informationen, daß Apache und andere ASP Server eine Antwort geben, aber nicht wie die aussehen muß. Es gibt wohl eine Menge von Paketen, die sich um die Bewertung von Inhalten kümmern, und man nur einbinden muß in ein eigenes oder fremdes Produkt. Da gibt es so wie es aussieht alles vorgefertigt, aber ich finde keine genaue Beschreibung einer "Low-Level Response". Weiß jemand wie die auszusehen hat?

Viele Grüße,
Semo
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Webserver mit Java schreiben? Netzwerkprogrammierung 4
S Socket Webserver mit SSLSocket geht nicht Netzwerkprogrammierung 1
B HTML mit Webserver und Datenbank verbinden Netzwerkprogrammierung 2
Z Debug-Info einer JavaSE Applikation auf Webserver Netzwerkprogrammierung 0
K Webserver mit Ethernet-Device verbinden Netzwerkprogrammierung 0
S Webserver für Jar File Netzwerkprogrammierung 4
F Java App mit Webserver Netzwerkprogrammierung 4
L Webserver pingen Netzwerkprogrammierung 5
TiME-SPLiNTER HTTP User Authentication: Java Client -> Webserver Netzwerkprogrammierung 7
Semox Socket Selbstgeschriebenen Webserver im lokalen Netzwerk publizieren? Netzwerkprogrammierung 4
I HTTP Grundlagen um einen Webserver zu erstellen Netzwerkprogrammierung 17
L Javaprogramm auf Webserver Netzwerkprogrammierung 5
M Java-Programm als Webserver erzeugt HTML Netzwerkprogrammierung 8
S Verständnisproblem concurrent - iterativer Webserver Netzwerkprogrammierung 2
D "FileChooser" auf einem Webserver Netzwerkprogrammierung 5
F Empfehlung für embedded Webserver Netzwerkprogrammierung 10
F Webserver Zugriff per Java Netzwerkprogrammierung 3
sparrow Connection Reset bei Webserver, Java WebStart als Client Netzwerkprogrammierung 9
H Webserver mit PHP als Java-Programm, gibt es schon so etwas? Netzwerkprogrammierung 12
C Socketkommunikation mit Webserver Netzwerkprogrammierung 5
J Webserver auf einem Pocket PC Netzwerkprogrammierung 2
M sessionhandling beim webserver Netzwerkprogrammierung 5
B Laden einer *.csv Datei von einem Webserver (http-request) Netzwerkprogrammierung 8
A Webserver - Bild senden Netzwerkprogrammierung 2
Rudolf Socket Externe IP holen und in Textfeld setzen Netzwerkprogrammierung 3
B FTP Externe Library von FTP-Server importieren Netzwerkprogrammierung 5
B Webstart + externe/lokale Plugins/JARS einbinden Netzwerkprogrammierung 10
M RMI lokal über externe IP geht nicht Netzwerkprogrammierung 5
S Datenbankzugriff auf externe Mysql DB Netzwerkprogrammierung 9
E Problem bei Sockets/InputStream über externe Klasse Netzwerkprogrammierung 5
B RMI externe/interne ip problem Netzwerkprogrammierung 2
Z externe IP ermitteln Netzwerkprogrammierung 16
B Zip Dateien über FTP laden Netzwerkprogrammierung 2
T MP3 Dateien Stream Netzwerkprogrammierung 3
I Kleine Dateien senden Netzwerkprogrammierung 3
J Socket Dateien über Socket auf Server speichern Netzwerkprogrammierung 3
F HTTP HTTP-Download: Dateien in einem Verzeichnis ermitteln Netzwerkprogrammierung 8
D Aus einer URL die Dateien lesen Netzwerkprogrammierung 5
D HTTP Checksumme von Dateien abfragen Netzwerkprogrammierung 2
Weltall 7 HTTP Dateien an PHP-Skript senden Netzwerkprogrammierung 11
M Dateien über TCP/IP senden Netzwerkprogrammierung 18
R Mehrere Dateien über einen Socket senden Netzwerkprogrammierung 2
J Mit der File Api Dateien von anderen Rechnern lesen ? Netzwerkprogrammierung 3
V Problem beim Senden von Dateien Netzwerkprogrammierung 4
E Upload großer Dateien? Netzwerkprogrammierung 5
D dateien kopieren, am localhost funktionierts, im netz nicht Netzwerkprogrammierung 2
J Java Programm für Upload von Dateien per HTTP Netzwerkprogrammierung 7
M dateien übertragen, probleme mit versch. Strömen? Netzwerkprogrammierung 4
V Dateien Auflisten Netzwerkprogrammierung 3
G Probleme mit Firewall beim empfangen von dateien über socket Netzwerkprogrammierung 6
flashfactor Dateien im Netzwerk kopieren Netzwerkprogrammierung 2
I Dateien schnell/synchron senden Netzwerkprogrammierung 2
S Dateien versenden Netzwerkprogrammierung 16
C Dateien über Sockets versenden? Netzwerkprogrammierung 10
S Dateien auf einem HTTP Server Netzwerkprogrammierung 2
N *.* Dateien versenden im Lan Netzwerkprogrammierung 5
O Dateien von einem Server laden Netzwerkprogrammierung 3
T Dateien wia P2P Connection versenden Netzwerkprogrammierung 2
W Server schickt Dateien jede 3 Sekonden Netzwerkprogrammierung 3
C Verzeichnisstrukturen & Dateien über Socketverb. übertra Netzwerkprogrammierung 12
A FileSend - Dateien verschicken Netzwerkprogrammierung 19

Ähnliche Java Themen


Oben