MadFrat: eigener kleiner Server in Java

Hallo,

angeregt durch eine interessante Vorlesung im noch aktuellen Wintersemester (Betriebssysteme, Rechnernetze und verteilte Systeme) habe ich mal versucht, selbst einen kleinen Server in Java zu schreiben.
Soweit klappt auch alles, bis auf das Ausliefern von Binärdateien.
Wenn ich die mit derselben Methode ausgeben lassen wie ASCII-Texte, sehen zB Bilder völlig kaputt aus. Und wenn ich versuche eine eigene Ausgabe für Binärdateien zu verwenden, werden einfach nur Zahlen rausgeworfen, die ein Browser auch nicht verwenden kann.

Weiss zufällig jemand, woran das liegen kann und wie man es anders machen sollte?
Die gelesenen Bytes vor der Ausgabe nach Char zu casten, bringt auch nichts.

Ich habe natürlich nicht den Anspruch Apache oder sonst wem Konkurrenz zu bieten. :D  Ist nur ein Projekt, um in Übung zu bleiben und auch mal ein bisschen was Grösseres zu schreiben.

  1. Hallo MadFrat!

    angeregt durch eine interessante Vorlesung im noch aktuellen Wintersemester (Betriebssysteme, Rechnernetze und verteilte Systeme) habe ich mal versucht, selbst einen kleinen Server in Java zu schreiben.

    Der Gedanke gefällt mir gut.

    Soweit klappt auch alles, bis auf das Ausliefern von Binärdateien.
    Wenn ich die mit derselben Methode ausgeben lassen wie ASCII-Texte, sehen zB Bilder völlig kaputt aus. Und wenn ich versuche eine eigene Ausgabe für Binärdateien zu verwenden, werden einfach nur Zahlen rausgeworfen, die ein Browser auch nicht verwenden kann.

    Ich vermute, du hast dich bloß noch nicht mit dem Http-Header befasst.
    Die beiden Zeilen aus http://forum.de.selfhtml.org/archiv/2004/1/t69170/#m398207 dürften den Ausschlag geben:
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename="$save_as_name"");

    Viele Grüße
    H-P Ortner

    1. Hallo,

      vielen Dank für die Antworten. Am Header liegt es auf jeden Fall nicht. Ich habe mittlerweile herausgefunden, dass es wohl daran liegt, dass der Browser die Bytes als ASCII-Zeichen anders interpretiert.
      Ich habe mal am Beispiel einer Bilddatei Original und Übertragung im Hex-Editor angeschaut und festgestellt, dass fast alle Werte identisch sind bis auf einige Ausnahmen. An diesen Stellen war der Wert in der Originaldatei entweder #84 (132), #8C (140), #94 (148) oder #9C (156) und in der fehlerhaften Datei auf #3F (63) gesetzt.

      Diese Werte werden alle zum Zeichen ?, wenn man das gelesene Byte nach char castet. Unter Linux werden wohl sogar noch mehr Werte mit ? dargestellt. Kann man da irgendwie einen festen Zeichensatz bestimmen?

  2. Hallo,

    angeregt durch eine interessante Vorlesung im noch aktuellen Wintersemester (Betriebssysteme, Rechnernetze und verteilte Systeme) habe ich mal versucht, selbst einen kleinen Server in Java zu schreiben.
    Soweit klappt auch alles, bis auf das Ausliefern von Binärdateien.
    Wenn ich die mit derselben Methode ausgeben lassen wie ASCII-Texte, sehen zB Bilder völlig kaputt aus. Und wenn ich versuche eine eigene Ausgabe für Binärdateien zu verwenden, werden einfach nur Zahlen rausgeworfen, die ein Browser auch nicht verwenden kann.

    Weiss zufällig jemand, woran das liegen kann und wie man es anders machen sollte?
    Die gelesenen Bytes vor der Ausgabe nach Char zu casten, bringt auch nichts.

    Der HTTP-Response, den Du am besten über einen OutputStream in den OutputStream des Sockets schreibst, muss so aussehen:
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6

    Response      = Status-Line               ; Section 6.1
                           *(( general-header        ; Section 4.5
                            | response-header        ; Section 6.2
                            | entity-header ) CRLF)  ; Section 7.1
                           CRLF
                           [ message-body ]          ; Section 7.2

    Beispiel für ein Gif-Bild von 50000 Octets Länge. CRLF = "\r\n":

    HTTP/1.1 200 OK CRLF
    Content-Type: image/gif CRLF
    Content-Length: 50000 CRLF
    CRLF
    [Byte-Daten des Bildes]

    Wenn das Bild eine auf dem Server gespeicherte Datei ist, dann bekommst Du diese am günstigsten über einen

    FileInputStream fis = new FileInputStream(docroot.concat(requestURI.getPath()));

    docroot wäre Dein Document-Root und requestURI die ausgelesene URI des Requests.
    Content-Length wäre damit:

    new Integer(fis.available())

    und die Bytedaten könnte eine

    private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception {
    byte[] buffer = new byte[1024] ;
    int bytes = 0 ;
    while ((bytes = fis.read(buffer)) != -1 ) {
         os.write(buffer, 0, bytes);
    }
        }

    in den OutputStream des Sockets senden.

    viele Grüße

    Axel