Avatar billede langkiller Nybegynder
07. marts 2013 - 22:44 Der er 36 kommentarer og
1 løsning

Http webserver - tutorials/hints

Sidder og vil prøve at lave en webserver i java. Den skal kunne forstå http/1.0 og GET requests.
Derudover skal den gerne kunne tilbyde at vise filer fra et www directory og sende en http 200 besked tilbage, samt filens indhold. i 200 requestens header skulle der også gerne være nogle linjer der viser filtype og filstørrelse. Man skulle gerne kunne tilgå filerne via browseren, men har ikke rigtig nogen ide om hvordan eller hvad der skal skrives i browseren for at gøre dette.

Jeg synes virkelig jeg har ledt over alt for at finde nogle guides/tutorials, men kan kun finde færdige løsninger uden forklaringer. Så håber at nogen herinde ligger inde med noget der kunne hjælpe mig på vej
Avatar billede arne_v Ekspert
07. marts 2013 - 22:49 #1
Vil du skrive en HTTP server for at laere noget ved det eller fordi at du skal bruge en?

Hvis du bare skal bruge en, saa er det nemt at embedded Jetty i en Java applikation.

Hvis du vil laere noget ved det skal du i gang med socket programmering og thread programmering.

Jeg vil klart anbefale at starte med et simpelt design.
Avatar billede langkiller Nybegynder
07. marts 2013 - 23:13 #2
det er for at lære noget. og skulle gerne ende op med ovenstående.
det ville være super med guide til socket(thread) programmering der bygger op til at lave en webserver.

når du siger et simpelt design, hvordan mener du så?
Avatar billede arne_v Ekspert
07. marts 2013 - 23:21 #3
main med serversocket og en loekke som accepterer en socket og saa starter en traad til at haandtere request (hvis request faar sit eget objekt og socket sendes med over i constructor).

Det kan laves rimeligt simpelt.

Start med at lade alle request modtage "OK" tilbage og byg saa ovenpaa dette.
Avatar billede langkiller Nybegynder
07. marts 2013 - 23:22 #4
Det ville også være en rigtig stor hjælp med et simpelt eksempel og en lille forklaring på hvordan det fungerer
Avatar billede langkiller Nybegynder
07. marts 2013 - 23:34 #5
hmm okay.. hvordan ville det se ud? ved ikke hvordan man laver det fordi jeg ikke kan finde nogle eksempler eller guides der beskriver det fra bunden af.

Hvad gør en request helt præcis? er det noget med at spørger om en fil finde og så få en fejl eller informationer retur?
Avatar billede arne_v Ekspert
07. marts 2013 - 23:37 #6
Jeg kan proeve at bixe noget.
Avatar billede arne_v Ekspert
07. marts 2013 - 23:40 #7
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpelHttpServer {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(88);
            while(true) {
                Socket s = ss.accept();
                (new RequestHandler(s)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class RequestHandler extends Thread {
    private BufferedReader br;
    private PrintWriter pw;
    public RequestHandler(Socket s) throws IOException {
        br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
    }
    @Override
    public void run() {
        try {
            String req = br.readLine();
            String[] parts = req.split(" ");
            String method = parts[0];
            String path = parts[1];
            String version = parts[2];
            pw.println("HTTP/1.0 200 OK");
            pw.println("Content-Type: text/plain");
            pw.println();
            pw.printf("method=%s path=%s version=%s", method, path, version);
            pw.flush();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Avatar billede langkiller Nybegynder
07. marts 2013 - 23:50 #8
Fedt! Hvordan ville klient siden se ud til den? er jeg også ret meget i tvivl om hvordan skal se ud og hvilken slags input der ind.
Er også i tvivl om:
- hvor man skal placerer sine filer hvis der f.eks. skal spørges efter en html side e.l.?

- Hvad man skal skrive i sin browser for at få adgang til java serveren? er det en ip adresse eller portnummer eller noget helt tredje?

men ovenstående returnerer OK 200 uanset hvad man spørger efter ikke?
Avatar billede langkiller Nybegynder
07. marts 2013 - 23:51 #9
men vil i hvert fald gå igang med at studerer din kode nærmere, det er allerede en kæmpe stor hjælp!
Avatar billede langkiller Nybegynder
08. marts 2013 - 00:18 #10
okay min #8 kommentar var jeg vist lige lidt for hurtig med at skrive. jeg prøver igen:
- Hvordan ville klient siden/programmet til den se ud?
- Hvilken slags input skal den have? altså fra klienten
- Hvor skal man placerer de filer man vil spørge efter? f.eks. html sider osv.?
- Hvordan får man adgang til serveren gennem browseren? er det ved at skrive ip, portnummer eller noget helt tredje i adresse feltet?
Avatar billede arne_v Ekspert
08. marts 2013 - 01:09 #11
Normalt bruger man en web browser som client til en web server.
Avatar billede arne_v Ekspert
08. marts 2013 - 01:10 #12
Jeg valgte port 88 saa:

http://localhost:88/etellerandet
Avatar billede arne_v Ekspert
08. marts 2013 - 01:11 #13
Du udtraekker path som angivet i mit lille demo program og kan bruge det til at returnere indhold af filer fra hvor du nu har lyst til.
Avatar billede langkiller Nybegynder
10. marts 2013 - 15:33 #14
hvor ville man så typisk returnere filer fra ?
prøvede lige at lave lidt om i det der skulle skrives til browseren i dit eksempel(det hvor der står path oscv.), hvor jeg tilføjede lidt html, men det kunne den ikke vise i browserer. Den udskrev bare html koden.
Men det kan den måske godt hvis man tager indholdet fra en html fil og udskriver det i browseren med sin java server?
kan man få indholdet fra en html fil ved at bruge FileInputStream? eller er det ikke det mest hensigtsmæssige?
Avatar billede arne_v Ekspert
10. marts 2013 - 16:22 #15
Hvis du vil sende HTML skal du rette:

pw.println("Content-Type: text/plain");

til:

pw.println("Content-Type: text/html");
Avatar billede arne_v Ekspert
10. marts 2013 - 16:22 #16
Du kan selv bestemme hvilket dir dit program skal serve filer fra.
Avatar billede arne_v Ekspert
10. marts 2013 - 16:23 #17
FileInputStream eller FileReader var oplag til at laese HTML filer med.

FileInputStream til billeder og andre binaere filer.
Avatar billede langkiller Nybegynder
12. marts 2013 - 09:43 #18
hvordan kan jeg få den til at vise et billede i browseren. Det går helt fint med at læse html filer ind i browseren. Har forstået at der ved billeder skal bruges image/jpg istedet for text/html, men det er vel ikke det eneste der skal gøres. Har læst noget med at man skal læse bytes ind og på en eller anden måde smide det videre, men kan ikke helt finde ud af hvordan det skal gøres.

Prøvede først at gøre sådan her, men det virkede selvfølgelig ikke med billedet:

pw.println("HTTP/1.0 200 OK");
               
                    if (fString.endsWith(".html")) {
                        pw.println("Content-Type: text/html");
                        System.out.println("html");
                      }
                    else if (fString.endsWith(".jpg") || fString.endsWith(".jpeg")) {
                        pw.println("Content-Type: image/jpg");
                        System.out.println("jpg");
                      } else {
                        pw.println("Content-Type: text/plain");
                          System.out.println("unkown filetype!");
                      }
   
                    FileReader fr = new FileReader(f);
                    BufferedReader br = new BufferedReader(fr);
                        String nextLine;
                        String pageContent = "";
                        while((nextLine = br.readLine()) != null) {
                            pageContent = pageContent + " " + nextLine;
                        }
                    fr.close();
                   
                pw.println();
                pw.printf(pageContent);
                pw.flush();
                pw.close();
Avatar billede langkiller Nybegynder
12. marts 2013 - 10:13 #19
ups ! prøver lige med fileinputstream istedet :)
Avatar billede langkiller Nybegynder
12. marts 2013 - 10:25 #20
nu viser den et "knækket billed ikon", som om den prøver at hente et billede der ikke findes. Men har tjekket den path der bliver brugt og den passer. Kan ikke helt finde ud af hvad der er galt med koden.


    File f           = new File("C:/javaServer/"+path);
                String fString = f.getPath();
               
                    if (!f.isFile() && !f.canRead()) {
                        f = new File("C:/javaServer/errorPage.html");
                    }
                   


                pw.println("HTTP/1.0 200 OK");
               
                    if (fString.endsWith(".html")) {
                       
                            FileReader fr = new FileReader(f);
                            BufferedReader br = new BufferedReader(fr);
                                String nextLine;
                                String pageContent = "";
                                while((nextLine = br.readLine()) != null) {
                                    pageContent = pageContent + " " + nextLine;
                                }
                            fr.close();

                            pw.println("Content-Type: text/html");
                            pw.println();
                            pw.printf(pageContent);
                           
                      }
                    else if (fString.endsWith(".jpg") || fString.endsWith(".jpeg")) {

                        InputStream picInputStream = new FileInputStream(fString);
                        BufferedImage image = ImageIO.read(picInputStream); 
                        pw.println("Content-Type: image/jpg");
                        pw.println();
                        pw.print(image);
                        System.out.println(image);
                        System.out.println(fString);
                       
                      } else {
                        pw.println("Content-Type: text/plain");
                          System.out.println("unkown filetype!");
                      }
                   
                pw.flush();
                pw.close();
Avatar billede arne_v Ekspert
12. marts 2013 - 14:12 #21
PrintWriter duer ikke til binaere filer.

Og du skal ikke bruge Image.

Laes et byte[] ind fra en FileInputStream og skriv dem til en OutputStream (som saa skal saettes op i constructor).
Avatar billede langkiller Nybegynder
16. marts 2013 - 00:52 #22
hmm har googlet lidt og kommet frem til at dette skulle kunne lade sig gøre:


                File f           = new File("C:/javaServer/"+path);
byte pageContent = 0;
                        byte[] fileContent = Files.readAllBytes(f.toPath());
                        pw.print(pageContent);

den skrive dog bare 0 ud.. nogen ide om hvorfor ?
Avatar billede langkiller Nybegynder
16. marts 2013 - 00:57 #23
dooh skrev noget helt forkert. glem det jeg lige skrev! har følgende:

File f          = new File("C:/javaServer/"+path);
byte[] pageContent = Files.readAllBytes(f.toPath());
pw.print(pageContent);

og den udskriver: [B@142bece
Avatar billede arne_v Ekspert
16. marts 2013 - 03:20 #24
PrintWriter duer ikke til binaere data - brug OutputStream.

os.write(pageContent, 0, pageContent.length);
Avatar billede langkiller Nybegynder
17. marts 2013 - 21:04 #25
kan ikke helt finde ud af hvad OutputStream skal have som input.
man kan nemlig ikke bare skrive:
os = new OutputStream();
i eclipse siger den noget med "cannot instantiate the type OutputStream".

hvad betyder det 0 forresten? er der hvor den skal starte med at læse fra i byte arrayet?
Avatar billede langkiller Nybegynder
17. marts 2013 - 21:13 #26
ahh det virkede da jeg prøvede med dataoutputstream istedet!
men det er måske ikke det meste hensigtsmæssige?
Avatar billede arne_v Ekspert
18. marts 2013 - 00:18 #27
OutputStream er en abstrakt klasse og kan derfor ikke instantieres.

Du henter den ud af Socket og du skal bare gemme en ref til den.
Avatar billede arne_v Ekspert
18. marts 2013 - 00:19 #28
Jeg vil anbefale at undgaa DataInputStream og DataOutputStream indtil du har brug for at sende integer og floating point i big endian format.
Avatar billede langkiller Nybegynder
18. marts 2013 - 09:53 #29
hvad mener du med bare at gemme en ref til den? hvordan skal det se ud.

det er jo ikke nok bare at skrive

    private OutputStream os;

os.write(pageContent, 0, pageContent.length);
Avatar billede langkiller Nybegynder
18. marts 2013 - 10:24 #30
undskyld manglede lige denne
os = s.getOutputStream();


det virker i chrome, men ikke firefox(den viser bare en masse tegn)..

dataoutputstreaam opførte sig på præcis samme måde
Avatar billede arne_v Ekspert
18. marts 2013 - 15:57 #31
Hvordan ser koden ud nu?
Avatar billede langkiller Nybegynder
18. marts 2013 - 16:30 #32
requesthandler klassen
http://pastebin.com/A96st2fE
Avatar billede arne_v Ekspert
18. marts 2013 - 16:42 #33
Jeg kan ikke se at du saetter Content-Type !?
Avatar billede langkiller Nybegynder
18. marts 2013 - 16:53 #34
nej det har du da ret i.
men prøvede lige at tilføje det til visning af html filer
pw.printf("Content-Type: text/html");
                            String pageContent = "";
                            pageContent = getContent.getHtmlContent(f);
                            pw.printf(pageContent);

den viser bare koden som tekst i browseren nu ?
Avatar billede arne_v Ekspert
19. marts 2013 - 02:39 #35
Er der en blank linie mellem sidste header og content?
Avatar billede langkiller Nybegynder
03. april 2013 - 22:50 #36
undskyld, jeg glemte helt tråden her. Fik det til at køre som det skulle. Tak for hjælpen ! Smid et svar
Avatar billede arne_v Ekspert
03. april 2013 - 23:48 #37
kommer her
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester