Avatar billede strcoder Nybegynder
06. september 2004 - 13:42 Der er 9 kommentarer og
1 løsning

prob. med java webserver

Hej Java folks, jeg har gang i Nordfalks webserver eksempel (javabog.dk kap. 16.2), og forsøger at udbygge det.

Mit problem består i at 'streame' billeder ud til klienten, jeg har forsøgt at lave en metode 'hentBinFil' der skulle klare opgaven, men jeg får kun stack-adressen ud til klienten :)

Jeg har vedlagt hele koden, og er mere end tilfreds med et skub i den rigtige retning, jeg behøver ikke at få det hele foræret (skulle jo gerne lære lidt :)

-------- Kode start ---------------------------------------
import java.io.*;
import java.util.*;
import java.net.*;

public class JavaServer
{
  public static void main(String[] arg)
  {
      int antal = 0;
      boolean binfil = false;
      OutputStream binside = null;

       
      konsol("Min Java web-server ver. 0.0.1");
     
    try
    {
      ServerSocket socket = new ServerSocket(80);

      while (true)
      {
        Socket forb = socket.accept();
        PrintWriter ud    = new PrintWriter(forb.getOutputStream());
        BufferedReader ind = new BufferedReader(new InputStreamReader(forb.getInputStream()));
       
        String anmodning = ind.readLine();
        System.out.println("anmodning: " + anmodning);
        if(anmodning.equals(""))
            anmodning = "tom tom tom";
       
        StringTokenizer bidder = new StringTokenizer(anmodning);
        String metode = bidder.nextToken();
        String filsti = bidder.nextToken();
        String protekol = bidder.nextToken();
       
        if(filsti.equals("/"))
            filsti = "/index.htm";
       
        if(filsti.indexOf(".gif") != -1)
              binfil = true;
       
            try
            {
            if(binfil)
            {
                binside = hentBinFil(filsti);
                Writer out = new BufferedWriter(new OutputStreamWriter(binside));
                PrintStream ps = new PrintStream(binside);
               
                ud.println("Content-type: image/gif");
                  ud.println();
                ud.println(ps);
            }else{
                ud.println("HTTP/0.9 200 OK");
                  ud.println();
                ud.println(hentFil(filsti));
            }
            }catch(IOException e){
            if(binfil)
            {
                ud.println("HTTP/0.9 200 OK");
                  ud.println();
                ud.println("404 binfil");
            }else{
                ud.println("HTTP/0.9 200 OK");
                  ud.println();
                ud.println(hentFil("/404.htm"));
            }
            }
           
            antal += 1;
            konsol("" + antal + " " + filsti.replaceAll("index.htm","") + "");
           
        ud.flush();
        forb.close();
      }
    }catch(Exception e){
      e.printStackTrace();
    }
  }
 
  public static String hentFil(String filsti) throws IOException
  {
      String html = "";
     
    FileReader fil = new FileReader("c:\\java\\webserver" + filsti);
    BufferedReader ind = new BufferedReader(fil);

    String linie = ind.readLine();
    while (linie != null)
    {
      html = html + linie;
      linie = ind.readLine();
    }
   
    return html;
  }
 
  public static OutputStream hentBinFil(String filsti) throws IOException
  {
    InputStream is = new FileInputStream("c:\\java\\webserver" + filsti);
    OutputStream os = new FileOutputStream("c:\\java\\webserver\\tmp\\" + filsti);
   
    // brug buffere i læsning og skrivning (mere effektivt)            punkt A
    is = new BufferedInputStream(is);
    os = new BufferedOutputStream(os);

    // læs og skriv én byte ad gangen (ret ineffektivt)                punkt B
    int b = is.read();
    while (b != -1)
    {
      os.write(b);
      b = is.read();
    }

    is.close();
    os.flush();
    os.close();
   
    return os;
  }
 
  private static void konsol(String tekst)
  {
      System.out.println("Server--> " + tekst);
  }
}
-------- Kode slut  ---------------------------------------
Avatar billede arne_v Ekspert
06. september 2004 - 13:45 #1
hentBinFil skal vel læse bytene og returnere et byte array (i.s.f. en stream) ??
Avatar billede arne_v Ekspert
06. september 2004 - 13:50 #2
Hvis hentBinFil allokerer et byte array af filens størrelse, læser alle
bytes op i det og returnerer det.

Så kan din hoved kode skrive det byte array ud. Ikke på PrintWriter med
println men på OutputStream med write.

Altså forb.getOutputStream().
Avatar billede arne_v Ekspert
06. september 2004 - 13:51 #3
Jeg kan sagtens lave det, men du vil jo helst selv arbejde lidt med det (hvilket
er meget fornuftigt !)
Avatar billede strcoder Nybegynder
06. september 2004 - 13:55 #4
Jeg prøver lige om jeg kan finde ud løsningen ud fra dine anvisninger.
Avatar billede strcoder Nybegynder
07. september 2004 - 12:29 #5
Jeg må indrømme at jeg har mine problemer :) jeg fandt et eksempel på nettet og har forsøgt at lave hentBinFil() om så den retunerer et byte array.

Jeg tror egentligt det virker, men jeg kan ikke regne ud hvordan jeg så får sendt det ud til klienten vha. forb.getOutputStream() med .write

Måske hvis du smed et eksempel alligevel :) så kunne jeg studere det og så måske endda forstå det.

-------- kode start ------------------------------------
    public static byte[] hentBinFil(File fil) throws IOException
    {
        InputStream is = new FileInputStream(fil);    // nyt filobjekt
        long length = fil.length();                                    // filstørrelse
       
        if (length > Integer.MAX_VALUE){ }
       
        byte[] b = new byte[(int)length];                        // byte array
       
        int o = 0;
        int n = 0;
        while (o < b.length && (n=is.read(b, o, b.length-o)) >= 0)
            o += n;
       
        if (o < b.length)                                                        // alle bytes skal med
          throw new IOException("Fik ikke hele filen " + fil.getName());
       
        is.close();                                                                    // luk
        return b;                                                                        // retuner
    }
-------- kode slut  ------------------------------------
Avatar billede arne_v Ekspert
07. september 2004 - 12:38 #6
public byte[] readfile(String filename) throws IOException {
      byte[] b = new byte[(int) (new File(filename)).length()];
      InputStream is = new FileInputStream(filename);
      is.read(b);
      is.close();
      return b;
  }

(forudsætter hele filen kan være i memory)
Avatar billede arne_v Ekspert
07. september 2004 - 12:40 #7
ud.println("Content-type: image/gif");
ud.println();
ud.flush();
forb.flush();
forb.getOutputStream().write(readfile(filnavn));
forb.flush();
Avatar billede arne_v Ekspert
07. september 2004 - 12:46 #8
Der er slet ikke så meget i det.
Avatar billede arne_v Ekspert
07. september 2004 - 22:08 #9
Her er et komplet eksempel som ligner dit eksempel lidt men som
alligevel er lidt anderledes:

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

public class WebServer {
    private final static int PORT = 80;
    private final static String PATH = "C:\\";
    public static void main(String[] arg) {
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(PORT);
        } catch (IOException e) {
            System.out.println("Can not bind to port " + PORT);
            System.exit(0);
        }
        while(true) {
            try {
                Socket s = ss.accept();
                InputStream is = s.getInputStream();
                OutputStream os = s.getOutputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                PrintWriter pw = new PrintWriter(os);
                String req = br.readLine();
                StringTokenizer st = new StringTokenizer(req, " ");
                String method = st.nextToken();
                String path = st.nextToken();
                String protocol = st.nextToken();
                if(path.equals("/")) {
                    path = "index.htm";
                }
                System.out.println(method + " " + path);
                boolean binary;
                String type;
                if(path.indexOf(".htm") > 0) {
                    binary = false;
                    type = "text/html";
                } else if(path.indexOf(".txt") > 0) {
                    binary = false;
                    type = "text/plain";
                } else if(path.indexOf(".gif") > 0) {
                    binary = true;
                    type = "image/gif";
                } else if(path.indexOf(".jpg") > 0) {
                    binary = true;
                    type = "image/jpeg";
                } else {
                    binary = true;
                    type = "application/octet-stream";
                }
                pw.println("HTTP/0.9 200 OK");
                pw.println("Content-Type: " + type);                   
                pw.println();                   
                pw.flush();
                os.flush();
                if(binary) {
                    sendBinary(path, os);
                } else {
                    sendText(path, pw);
                }
                os.flush();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
           
        }
    }
    private static void sendText(String filename, PrintWriter pw) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(PATH + filename)));
        String line;
        while((line = br.readLine()) != null) {
            pw.println(line);
        }
        pw.flush();
    }
    private static void sendBinary(String filename, OutputStream os) throws IOException {
        InputStream is = new FileInputStream(PATH + filename);
        byte[] b = new byte[100000];
        int n;
        while((n = is.read(b)) >= 0){
            os.write(b, 0, n);
        }
    }
}
Avatar billede strcoder Nybegynder
08. september 2004 - 07:53 #10
Jeg fik det til at virke, tak for eksemplerne, det var mere simpelt end jeg havde troet :)

Jeg fortsætter med at gøre den flertrådet iht. Nordfalks bog, så skal der løses lidt problemer med f.eks. at klienten 'resetter' forbindelsen det laver en undtagelse der afslutter programmet. Jeg håber på at når trådene er indført så er det kun den enkelte tråd der vil blive afsluttet hvis klienten resetter.

Tak for hjælpen.
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