2013-08-08 17 views
7

Ich hosste eine Webseite von zu Hause aus. Ich habe meinen eigenen HTTP-Server mit Java erstellt. Dies ist ein SSCCE:Java HTTP Server funktioniert nicht

if(command.startsWith("GET")) 
{ 
      //client is a socket on which I reply. 
      PrintWriter pw = new PrintWriter(client.getOutputStream(), true); 
    String commule = command.split(" "); 
    if(commule[0].equals("GET")) 
    { 
     if(commule[1].contains(".")) 
     { 
      File file = new File(GEQO_SERVER_ROOT + commule[1].substring(1).replaceAll("%20", " ")); 
      if(file.exists()) 
      { 
       OutputStream out = client.getOutputStream(); 
       InputStream stream = new FileInputStream(file); 

       String response = new String(); 
       response += "HTTP/1.1 200 OK\r\n"; 
       response += "Date: Thu, 08 Aug 2013 08:49:37 GMT\r\n"; 
       response += "Content-Type: text/html\r\n"; 
       response += "Content-Length: " + file.length() + "\r\n"; 
       response += "Connection: keep-alive\r\n"; 
       response += "\r\n"; 
       pw.write(response); //Assume I already initialized pw as a PrintWriter 
            pw.flush(); 
       copy(stream, out); 
       stream.close(); 
       out.close(); 
      } 
      else 
      { 
       pw.write("<html><h1>The request 404ed.</h1>"); 
       pw.write("<body>The requested URL <b>" + commule[1] + "</b> could not be found on this server.</body></html>"); 
            pw.flush(); 
      } 
     } 
     else 
     { 
      BufferedReader br = new BufferedReader(new FileReader(GEQO_SERVER_ROOT + commule[1].substring(1) + "main.html")); 
      String sCurrentLine; 
      while ((sCurrentLine = br.readLine()) != null) 
      { 
       pw.print(sCurrentLine); 
      } 
      br.close(); 
     } 
    } 
    else 
    { 
     pw.println("Unrecognized HTTP command."); 
    } 
} 

Dies ist die main.html Quelle:

<html>
<title>Geqo Server</title>
<body>Geqo server online and functioning!</body>
</html>

Das Problem ist, dass wenn ich versuche, auf diese Seite zuzugreifen unter Verwendung von Chrome, es wird korrekt angezeigt (zumindest bei Verwendung von 127.0.0.1). Aber als ich versuchte, auf Firefox auf 127.0.0.1 zuzugreifen, funktioniert es, aber gibt mir nur die HTML-Quelle. IE gibt mir auch nur die Quelle. Kann mir jemand sagen, warum Firefox und IE nur die Quelle anzeigen, anstatt es zu analysieren?

Ich denke, das enthält einige Hinweise (Firebug Screenshot):

Firebug screenshot

Meine Quelle in einem <pre> Tag kommt zu sein scheint. Ich weiß nicht warum, aber ist das nicht das Problem?

Ich Port-weitergeleitet. Hier ist die Seite Jungs: http://110.172.170.83:17416/ (Sorry, Stackoverflow erlaubt keine numerischen Verknüpfungen.)

EDIT: Ich habe das Problem gefunden. Aber bevor ich das erkläre, danke an Bart für den SSCCE, den ich mit meinem Code verglichen habe. Das ist das Problem: Die if Anweisung in der achten Zeile if(commule[1].contains(".")) bewirkt, dass der Code den Großteil des Codes hier überspringt. In diesem entsprechenden else Block gibt es sogar keinen Befehl zum Senden der Header. Danke an artbristol für das hinweisend.

Vielen Dank im Voraus.

+0

scheint in Ordnung zu sein. Könnte sein, dass die Header auf Ihrer Betriebssystem-Plattform nicht korrekt sind, wie für '\ r \ n' und Chrome macht einige Annahmen. – PeterMmm

+0

Ich denke nicht. Ich bin auf Windows 7 und außerdem funktioniert es in Chrome. – Hele

+0

Mit Firebug in Firefox ist der Inhaltstyp, den die Antwort für google.com hat, 'text/html; charset = UTF-8', versuchen Sie, den Zeichensatz hinzuzufügen, nur um zu sehen, was passiert – morgano

Antwort

5

Ihr Drucker wird nicht gespült (wie Ernest darauf hingewiesen hat), daher werden keine HTTP-Header gesendet. Sehen Sie sich das Ergebnis der direkten Verbindung an - es gibt nur die Rohdaten ohne Header zurück.

nc 110.172.170.83 17416 
GET/

<html><title>Geqo Server</title><body>Geqo server online and functioning!</body></html> 

einen HTTP-Server zu schreiben ist harte Arbeit . Sofern es sich nicht um eine Übung handelt, sollten Sie eine leichtgewichtige Version wie Jetty oder den integrierten Sun HTTP-Server im JDK verwenden.

Bearbeiten - A PrintWriter ist wirklich nicht geeignet für HTTP. Es wurde entwickelt, um mit zeilenweisen Daten wie einer Datei umzugehen, die auf die Festplatte geschrieben wird. Es hängt auch von plattformspezifischen Einstellungen für die Textkodierung und Zeilenenden ab. Überprüfen Sie die HTTP spec für weitere Details, wie ein ordnungsgemäßer HTTP-Server funktionieren sollte.

+0

Ja, es ist nur eine Übung. :) – Hele

+0

+1 tatsächlich habe ich es auch versucht. Ich glaube nicht, dass Sie den von mir vorgeschlagenen "Flush" -Ruf hinzugefügt haben! –

+0

Überprüfen Sie den aktualisierten Code. Ich fügte bündig hinzu.Wenn Sie jetzt versuchen, eine Verbindung zu meiner IP herzustellen, können Sie das Ergebnis sehen. Ich spüle. – Hele

1

Es scheint einige mögliche Probleme mit der Pufferung zu geben. Sie schreiben etwas von Ihrer Ausgabe in einen PrintWriter Wrapper um out, und andere Ausgabe direkt an out. Ich würde definitiv einen Anruf zu pw.flush() nach dem pw.write() Aufruf hinzufügen.

+0

Ich habe es gerade versucht. Aber das Problem besteht immer noch. – Hele

0

Sie senden keine Antwortheader.

Ich kann die Definition von pw in Ihrem Quellcode nicht finden?

+0

Es gibt einen Kommentar danach, dass es initialisiert wird. Bitte überprüfen Sie die Frage. – Hele

+0

Meine Schuld. Trotzdem wäre es gut zu sehen, wie der PrintWriter initialisiert wird. –

+0

Ich habe meine Frage aktualisiert. Bitte prüfe. – Hele

1

Sie aktiviert autoFlush mit dem zweiten Argument

new PrintWriter(client.getOutputStream(), true) 

http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html

Im Gegensatz zur Print Klasse, wenn die automatische Spülung aktiviert ist, wird es nur dann erfolgen, wenn eine der println, printf, oder format-Methoden werden aufgerufen, statt immer dann, wenn ein Newline-Zeichen ausgegeben wird. Diese Methoden verwenden den plattformeigenen Begriff des Zeilentrennzeichens anstelle des Zeilenvorschubzeichens.

Also im Grunde Ihre pw.write() nicht auf den Ausgangsstrom flush. Also alles, was Sie tun müssen, ist

pw.write(response); 

mit

pw.println(response); 
ersetzen
+0

Nur versucht, dass - funktioniert nicht :( – Hele

+1

Ich habe einen [kleinen Test] (http://pastebin.com/QjjvCqmx) so nah wie möglich an Ihre Situation (vereinfacht) .Dieser Code ausgedruckt die HTML-Ausgabe bei ' write 'wurde aufgerufen und die geparste Version auf' println'. Hast du versucht den 'copy()' Aufruf wegzulassen und einfach eine einfache Zeichenkette zu drucken? – Bart

+0

Dein Code scheint zu funktionieren, hmmmm ...., aber meins tut es immer noch ' nt. Warte, laufe Tests .. – Hele